mirror of https://github.com/OpenTTD/OpenTTD
Add: Client setting gui.start_spectator
Activates a spectator slot in single player and initiate games as a spectatorpull/13673/head
parent
e70f20a781
commit
402660e447
|
@ -72,8 +72,8 @@ static int32_t ClickMoneyCheat(int32_t, int32_t change_direction)
|
|||
*/
|
||||
static int32_t ClickChangeCompanyCheat(int32_t new_value, int32_t change_direction)
|
||||
{
|
||||
while ((uint)new_value < Company::GetPoolSize()) {
|
||||
if (Company::IsValidID((CompanyID)new_value)) {
|
||||
while ((uint)new_value <= COMPANY_SPECTATOR) {
|
||||
if (Company::IsValidID((CompanyID)new_value) || (new_value == COMPANY_SPECTATOR && _settings_client.gui.start_spectator)) {
|
||||
SetLocalCompany((CompanyID)new_value);
|
||||
return _local_company.base();
|
||||
}
|
||||
|
@ -303,7 +303,7 @@ struct CheatWindow : Window {
|
|||
case STR_CHEAT_CHANGE_COMPANY: {
|
||||
SetDParam(0, val + 1);
|
||||
uint offset = WidgetDimensions::scaled.hsep_indent + GetStringBoundingBox(ce->str).width;
|
||||
DrawCompanyIcon(_local_company, rtl ? text_right - offset - WidgetDimensions::scaled.hsep_indent : text_left + offset, y + icon_y_offset);
|
||||
if (_local_company != COMPANY_SPECTATOR) DrawCompanyIcon(_local_company, rtl ? text_right - offset - WidgetDimensions::scaled.hsep_indent : text_left + offset, y + icon_y_offset);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -925,9 +925,6 @@ CommandCost CmdCompanyCtrl(DoCommandFlags flags, CompanyCtrlAction cca, CompanyI
|
|||
case CCA_DELETE: { // Delete a company
|
||||
if (reason >= CRR_END) return CMD_ERROR;
|
||||
|
||||
/* We can't delete the last existing company in singleplayer mode. */
|
||||
if (!_networking && Company::GetNumItems() == 1) return CMD_ERROR;
|
||||
|
||||
Company *c = Company::GetIfValid(company_id);
|
||||
if (c == nullptr) return CMD_ERROR;
|
||||
|
||||
|
|
|
@ -2246,7 +2246,7 @@ struct CompanyWindow : Window
|
|||
reinit |= this->GetWidget<NWidgetStacked>(WID_C_SELECT_HOSTILE_TAKEOVER)->SetDisplayedPlane((local || _local_company == COMPANY_SPECTATOR || !c->is_ai || _networking) ? SZSP_NONE : 0);
|
||||
|
||||
/* Multiplayer buttons. */
|
||||
reinit |= this->GetWidget<NWidgetStacked>(WID_C_SELECT_MULTIPLAYER)->SetDisplayedPlane((!_networking || !NetworkCanJoinCompany(c->index) || _local_company == c->index) ? (int)SZSP_NONE : 0);
|
||||
reinit |= this->GetWidget<NWidgetStacked>(WID_C_SELECT_MULTIPLAYER)->SetDisplayedPlane(((!_networking && (c->is_ai || local || _local_company != COMPANY_SPECTATOR)) || (_networking && (!NetworkCanJoinCompany(c->index) || _local_company == c->index))) ? (int)SZSP_NONE : 0);
|
||||
|
||||
this->SetWidgetDisabledState(WID_C_COMPANY_JOIN, c->is_ai);
|
||||
|
||||
|
@ -2512,6 +2512,11 @@ struct CompanyWindow : Window
|
|||
break;
|
||||
|
||||
case WID_C_COMPANY_JOIN: {
|
||||
if (!_networking) {
|
||||
if (_local_company == COMPANY_SPECTATOR) SetLocalCompany((CompanyID)this->window_number);
|
||||
break;
|
||||
}
|
||||
|
||||
this->query_widget = WID_C_COMPANY_JOIN;
|
||||
CompanyID company = this->window_number;
|
||||
if (_network_server) {
|
||||
|
|
|
@ -1480,8 +1480,7 @@ DEF_CONSOLE_CMD(ConReloadAI)
|
|||
return true;
|
||||
}
|
||||
|
||||
/* In singleplayer mode the player can be in an AI company, after cheating or loading network save with an AI in first slot. */
|
||||
if (Company::IsHumanID(company_id) || company_id == _local_company) {
|
||||
if (Company::IsHumanID(company_id)) {
|
||||
IConsolePrint(CC_ERROR, "Company is not controlled by an AI.");
|
||||
return true;
|
||||
}
|
||||
|
@ -1518,8 +1517,7 @@ DEF_CONSOLE_CMD(ConStopAI)
|
|||
return true;
|
||||
}
|
||||
|
||||
/* In singleplayer mode the player can be in an AI company, after cheating or loading network save with an AI in first slot. */
|
||||
if (Company::IsHumanID(company_id) || company_id == _local_company) {
|
||||
if (Company::IsHumanID(company_id)) {
|
||||
IConsolePrint(CC_ERROR, "Company is not controlled by an AI.");
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -328,16 +328,10 @@ void ChangeOwnershipOfCompanyItems(Owner old_owner, Owner new_owner)
|
|||
/* In all cases, make spectators of clients connected to that company */
|
||||
if (_networking) NetworkClientsToSpectators(old_owner);
|
||||
if (old_owner == _local_company) {
|
||||
/* Single player cheated to AI company.
|
||||
* There are no spectators in singleplayer mode, so we must pick some other company. */
|
||||
/* Single player company bankrupts. Move player to Spectator. */
|
||||
assert(!_networking);
|
||||
Backup<CompanyID> cur_company2(_current_company);
|
||||
for (const Company *c : Company::Iterate()) {
|
||||
if (c->index != old_owner) {
|
||||
SetLocalCompany(c->index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
SetLocalCompany(COMPANY_SPECTATOR);
|
||||
cur_company2.Restore();
|
||||
assert(old_owner != _local_company);
|
||||
}
|
||||
|
@ -609,10 +603,11 @@ static void CompanyCheckBankrupt(Company *c)
|
|||
default:
|
||||
case 10: {
|
||||
if (!_networking && _local_company == c->index) {
|
||||
/* If we are in singleplayer mode, leave the company playing. Eg. there
|
||||
* is no THE-END, otherwise mark the client as spectator to make sure
|
||||
* they are no longer in control of this company. However... when you
|
||||
* join another company (cheat) the "unowned" company can bankrupt. */
|
||||
/* If we are in singleplayer mode and if spectator mode isn't active,
|
||||
* leave the company playing. Eg. there is no THE-END, otherwise mark
|
||||
* the client as spectator to make sure they are no longer in control
|
||||
* of this company. However... when you join another company (cheat)
|
||||
* the "unowned" company can bankrupt. */
|
||||
c->bankrupt_asked.Set();
|
||||
break;
|
||||
}
|
||||
|
@ -624,8 +619,8 @@ static void CompanyCheckBankrupt(Company *c)
|
|||
* updating the local company triggers an assert later on. In the
|
||||
* case of a network game the command will be processed at a time
|
||||
* that changing the current company is okay. In case of single
|
||||
* player we are sure (the above check) that we are not the local
|
||||
* company and thus we won't be moved. */
|
||||
* player we ensure that the local company remains the same until
|
||||
* the end of StateGameLoop, where it could be changed. */
|
||||
if (!_networking || _network_server) {
|
||||
Command<CMD_COMPANY_CTRL>::Post(CCA_DELETE, c->index, CRR_BANKRUPT, INVALID_CLIENT_ID);
|
||||
return;
|
||||
|
@ -645,7 +640,11 @@ static void CompaniesGenStatistics()
|
|||
{
|
||||
/* Check for bankruptcy each month */
|
||||
for (Company *c : Company::Iterate()) {
|
||||
Backup<CompanyID> cur_company(_current_company);
|
||||
Backup<CompanyID> loc_company(_local_company);
|
||||
CompanyCheckBankrupt(c);
|
||||
loc_company.Restore();
|
||||
cur_company.Restore();
|
||||
}
|
||||
|
||||
Backup<CompanyID> cur_company(_current_company);
|
||||
|
|
|
@ -644,6 +644,9 @@ STR_GRAPH_PERFORMANCE_DETAIL_TOOLTIP :{BLACK}Show det
|
|||
STR_GRAPH_KEY_CAPTION :{WHITE}Key to company graphs
|
||||
STR_GRAPH_KEY_COMPANY_SELECTION_TOOLTIP :{BLACK}Toggle graph of this company
|
||||
|
||||
# Company list toolbar dropdown
|
||||
STR_COMPANY_LIST_NEW_COMPANY :New company
|
||||
|
||||
# Company league window
|
||||
STR_COMPANY_LEAGUE_TABLE_CAPTION :{WHITE}Company League Table
|
||||
STR_COMPANY_LEAGUE_COMPANY_NAME :{ORANGE}{COMPANY} {BLACK}{COMPANY_NUM} '{STRING}'
|
||||
|
|
|
@ -842,8 +842,8 @@ static void OnStartScenario()
|
|||
static void OnStartGame(bool dedicated_server)
|
||||
{
|
||||
/* 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());
|
||||
* or, in the case of starting as spectator or a dedicated server, a spectator. */
|
||||
SetLocalCompany((dedicated_server || _settings_client.gui.start_spectator) ? COMPANY_SPECTATOR : GetFirstPlayableCompanyID());
|
||||
|
||||
NetworkOnGameStart();
|
||||
|
||||
|
@ -862,23 +862,25 @@ static void MakeNewGameDone()
|
|||
return;
|
||||
}
|
||||
|
||||
/* Create a single company */
|
||||
DoStartupNewCompany(false);
|
||||
if (!_settings_client.gui.start_spectator) {
|
||||
/* Create a single company */
|
||||
DoStartupNewCompany(false);
|
||||
|
||||
Company *c = Company::Get(CompanyID::Begin());
|
||||
c->settings = _settings_client.company;
|
||||
Company *c = Company::Get(CompanyID::Begin());
|
||||
c->settings = _settings_client.company;
|
||||
|
||||
/* Overwrite color from settings if needed
|
||||
* COLOUR_END corresponds to Random colour */
|
||||
/* Overwrite color from settings if needed
|
||||
* COLOUR_END corresponds to Random colour */
|
||||
|
||||
if (_settings_client.gui.starting_colour != COLOUR_END) {
|
||||
c->colour = _settings_client.gui.starting_colour;
|
||||
ResetCompanyLivery(c);
|
||||
_company_colours[c->index] = c->colour;
|
||||
}
|
||||
if (_settings_client.gui.starting_colour != COLOUR_END) {
|
||||
c->colour = _settings_client.gui.starting_colour;
|
||||
ResetCompanyLivery(c);
|
||||
_company_colours[c->index] = c->colour;
|
||||
}
|
||||
|
||||
if (_settings_client.gui.starting_colour_secondary != COLOUR_END && HasBit(_loaded_newgrf_features.used_liveries, LS_DEFAULT)) {
|
||||
Command<CMD_SET_COMPANY_COLOUR>::Post(LS_DEFAULT, false, _settings_client.gui.starting_colour_secondary);
|
||||
if (_settings_client.gui.starting_colour_secondary != COLOUR_END && HasBit(_loaded_newgrf_features.used_liveries, LS_DEFAULT)) {
|
||||
Command<CMD_SET_COMPANY_COLOUR>::Post(LS_DEFAULT, false, _settings_client.gui.starting_colour_secondary);
|
||||
}
|
||||
}
|
||||
|
||||
OnStartGame(false);
|
||||
|
@ -1231,6 +1233,7 @@ void StateGameLoop()
|
|||
|
||||
Layouter::ReduceLineCache();
|
||||
|
||||
bool valid_local_company = _game_mode != GM_EDITOR && !_networking && _settings_client.gui.start_spectator && Company::IsValidID(_local_company);
|
||||
if (_game_mode == GM_EDITOR) {
|
||||
BasePersistentStorageArray::SwitchMode(PSM_ENTER_GAMELOOP);
|
||||
RunTileLoop();
|
||||
|
@ -1281,6 +1284,10 @@ void StateGameLoop()
|
|||
}
|
||||
|
||||
assert(IsLocalCompany());
|
||||
if (valid_local_company && !Company::IsValidID(_local_company)) {
|
||||
/* _local_company no longer exists due to bankruptcy. */
|
||||
SetLocalCompany(COMPANY_SPECTATOR);
|
||||
}
|
||||
}
|
||||
|
||||
/** Interval for regular autosaves. Initialized at zero to disable till settings are loaded. */
|
||||
|
|
|
@ -3377,11 +3377,10 @@ bool AfterLoadGame()
|
|||
* starting a new company. */
|
||||
StartScripts();
|
||||
|
||||
/* If Load Scenario / New (Scenario) Game is used,
|
||||
* 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 (!_networking || (_networking && _network_server && !_network_dedicated)) {
|
||||
/* If Load Scenario / New (Scenario) Game is used, a company does not exist yet.
|
||||
* Create one here whenever start_spectator is disabled.
|
||||
* 1 exception: dedicated network servers. Those can have 0 companies. */
|
||||
if (!_settings_client.gui.start_spectator && !_networking || (_networking && _network_server && !_network_dedicated)) {
|
||||
CompanyID first_human_company = GetFirstPlayableCompanyID();
|
||||
if (!Company::IsValidID(first_human_company)) {
|
||||
Company *c = DoStartupNewCompany(false, first_human_company);
|
||||
|
|
|
@ -1139,11 +1139,9 @@ struct ScriptDebugWindow : public Window {
|
|||
|
||||
this->SetWidgetDisabledState(WID_SCRD_SETTINGS, this->filter.script_debug_company == CompanyID::Invalid() ||
|
||||
GetConfig(this->filter.script_debug_company)->GetConfigList()->empty());
|
||||
extern CompanyID _local_company;
|
||||
this->SetWidgetDisabledState(WID_SCRD_RELOAD_TOGGLE,
|
||||
this->filter.script_debug_company == CompanyID::Invalid() ||
|
||||
this->filter.script_debug_company == OWNER_DEITY ||
|
||||
this->filter.script_debug_company == _local_company);
|
||||
this->filter.script_debug_company == OWNER_DEITY);
|
||||
this->SetWidgetDisabledState(WID_SCRD_CONTINUE_BTN, this->filter.script_debug_company == CompanyID::Invalid() ||
|
||||
(this->filter.script_debug_company == OWNER_DEITY ? !Game::IsPaused() : !AI::IsPaused(this->filter.script_debug_company)));
|
||||
}
|
||||
|
|
|
@ -230,6 +230,7 @@ struct GUISettings {
|
|||
bool show_date_in_logs; ///< whether to show dates in console logs
|
||||
bool newgrf_developer_tools; ///< activate NewGRF developer tools and allow modifying NewGRFs in an existing game
|
||||
bool ai_developer_tools; ///< activate AI/GS developer tools
|
||||
bool start_spectator; ///< activate a spectator slot in single player and initiate games as a spectator
|
||||
bool scenario_developer; ///< activate scenario developer: allow modifying NewGRFs in an existing game
|
||||
uint8_t settings_restriction_mode; ///< selected restriction mode in adv. settings GUI. @see RestrictionMode
|
||||
bool newgrf_show_old_versions; ///< whether to show old versions in the NewGRF list
|
||||
|
|
|
@ -816,6 +816,12 @@ def = false
|
|||
post_cb = [](auto) { InvalidateWindowClassesData(WC_GAME_OPTIONS); InvalidateWindowClassesData(WC_SCRIPT_DEBUG); InvalidateWindowClassesData(WC_SCRIPT_SETTINGS); }
|
||||
cat = SC_EXPERT
|
||||
|
||||
[SDTC_BOOL]
|
||||
var = gui.start_spectator
|
||||
flags = SettingFlag::NotInSave, SettingFlag::NoNetworkSync
|
||||
def = false
|
||||
post_cb = [](auto) { InvalidateWindowClassesData(WC_COMPANY); }
|
||||
|
||||
[SDTC_BOOL]
|
||||
var = gui.scenario_developer
|
||||
flags = SettingFlag::NotInSave, SettingFlag::NoNetworkSync
|
||||
|
|
|
@ -141,6 +141,7 @@ static void PopupMainToolbarMenu(Window *w, WidgetID widget, const std::initiali
|
|||
static const int CTMN_CLIENT_LIST = -1; ///< Show the client list
|
||||
static const int CTMN_SPECTATE = -2; ///< Become spectator
|
||||
static const int CTMN_SPECTATOR = -3; ///< Show a company window as spectator
|
||||
static const int CTMN_NEW_COMPANY = -4; ///< Create a new company
|
||||
|
||||
/**
|
||||
* Pop up a generic company list menu.
|
||||
|
@ -154,8 +155,19 @@ static void PopupMainCompanyToolbMenu(Window *w, WidgetID widget, CompanyMask gr
|
|||
|
||||
switch (widget) {
|
||||
case WID_TN_COMPANIES:
|
||||
if (!_networking) break;
|
||||
|
||||
if (!_networking) {
|
||||
if (_local_company == COMPANY_SPECTATOR) {
|
||||
bool human = false;
|
||||
for (CompanyID c = CompanyID::Begin(); c < MAX_COMPANIES; ++c) {
|
||||
if (Company::IsValidHumanID(c)) {
|
||||
human = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!human) list.push_back(MakeDropDownListStringItem(STR_COMPANY_LIST_NEW_COMPANY, CTMN_NEW_COMPANY, Company::GetNumItems() >= MAX_COMPANIES));
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* Add the client list button for the companies menu */
|
||||
list.push_back(MakeDropDownListStringItem(STR_NETWORK_COMPANY_LIST_CLIENT_LIST, CTMN_CLIENT_LIST));
|
||||
|
||||
|
@ -594,6 +606,17 @@ static CallBackFunction MenuClickCompany(int index)
|
|||
return CBF_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!_networking && _local_company == COMPANY_SPECTATOR) {
|
||||
if (index == CTMN_NEW_COMPANY) {
|
||||
extern Company *DoStartupNewCompany(bool is_ai, CompanyID company = CompanyID::Invalid());
|
||||
Company *c = DoStartupNewCompany(false);
|
||||
c->settings = _settings_client.company;
|
||||
SetLocalCompany(c->index);
|
||||
return CBF_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
ShowCompany((CompanyID)index);
|
||||
return CBF_NONE;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue