Index: src/ai/ai_core.cpp =================================================================== --- src/ai/ai_core.cpp (revision 27550) +++ src/ai/ai_core.cpp (working copy) @@ -62,6 +62,7 @@ cur_company.Restore(); InvalidateWindowData(WC_AI_DEBUG, 0, -1); + DeleteWindowById(WC_AI_SETTINGS, company); return; } Index: src/ai/ai_gui.cpp =================================================================== --- src/ai/ai_gui.cpp (revision 27550) +++ src/ai/ai_gui.cpp (working copy) @@ -177,7 +177,7 @@ GetConfig(slot)->Change((*it).second->GetName(), (*it).second->GetVersion()); } InvalidateWindowData(WC_GAME_OPTIONS, WN_GAME_OPTIONS_AI); - InvalidateWindowClassesData(WC_AI_SETTINGS); + DeleteWindowByClass(WC_AI_SETTINGS); DeleteWindowByClass(WC_QUERY_STRING); } @@ -311,7 +311,7 @@ this->vscroll = this->GetScrollbar(WID_AIS_SCROLLBAR); this->FinishInitNested(slot); // Initializes 'this->line_height' as side effect. - this->SetWidgetDisabledState(WID_AIS_RESET, _game_mode != GM_MENU && Company::IsValidID(this->slot)); + this->SetWidgetDisabledState(WID_AIS_RESET, _game_mode == GM_NORMAL && (this->slot == OWNER_DEITY && !Game::GetInstance()->IsDead()) || (Company::IsValidAiID(this->slot) && !Company::Get(this->slot)->ai_instance->IsDead())); this->vscroll->SetCount((int)this->visible_settings.size()); } @@ -375,7 +375,7 @@ for (; this->vscroll->IsVisible(i) && it != visible_settings.end(); i++, it++) { const ScriptConfigItem &config_item = **it; int current_value = config->GetSetting((config_item).name); - bool editable = _game_mode == GM_MENU || ((this->slot != OWNER_DEITY) && !Company::IsValidID(this->slot)) || (config_item.flags & SCRIPTCONFIG_INGAME) != 0; + bool editable = _game_mode != GM_NORMAL || (this->slot != OWNER_DEITY && (!Company::IsValidAiID(this->slot) || Company::Get(this->slot)->ai_instance->IsDead())) || (this->slot == OWNER_DEITY && Game::GetInstance()->IsDead()) || (config_item.flags & SCRIPTCONFIG_INGAME) != 0; StringID str; TextColour colour; @@ -438,7 +438,7 @@ VisibleSettingsList::const_iterator it = this->visible_settings.begin(); for (int i = 0; i < num; i++) it++; const ScriptConfigItem config_item = **it; - if (_game_mode == GM_NORMAL && ((this->slot == OWNER_DEITY) || Company::IsValidID(this->slot)) && (config_item.flags & SCRIPTCONFIG_INGAME) == 0) return; + if (_game_mode == GM_NORMAL && ((this->slot == OWNER_DEITY && !Game::GetInstance()->IsDead()) || (Company::IsValidAiID(this->slot) && !Company::Get(this->slot)->ai_instance->IsDead())) && (config_item.flags & SCRIPTCONFIG_INGAME) == 0) return; if (this->clicked_row != num) { DeleteChildWindows(WC_QUERY_STRING); @@ -519,7 +519,7 @@ break; case WID_AIS_RESET: - if (_game_mode == GM_MENU || !Company::IsValidID(this->slot)) { + if (_game_mode != GM_NORMAL || (this->slot != OWNER_DEITY && (!Company::IsValidAiID(this->slot) || Company::Get(this->slot)->ai_instance->IsDead())) || (this->slot == OWNER_DEITY && Game::GetInstance()->IsDead())) { this->ai_config->ResetSettings(); this->SetDirty(); } @@ -532,7 +532,7 @@ if (StrEmpty(str)) return; ScriptConfigItemList::const_iterator it = this->ai_config->GetConfigList()->begin(); for (int i = 0; i < this->clicked_row; i++) it++; - if (_game_mode == GM_NORMAL && ((this->slot == OWNER_DEITY) || Company::IsValidID(this->slot)) && (it->flags & SCRIPTCONFIG_INGAME) == 0) return; + if (_game_mode == GM_NORMAL && ((this->slot == OWNER_DEITY && !Game::GetInstance()->IsDead()) || (Company::IsValidAiID(this->slot) && !Company::Get(this->slot)->ai_instance->IsDead())) && (it->flags & SCRIPTCONFIG_INGAME) == 0) return; int32 value = atoi(str); this->ai_config->SetSetting((*it).name, value); this->SetDirty(); @@ -543,7 +543,7 @@ assert(this->clicked_dropdown); ScriptConfigItemList::const_iterator it = this->ai_config->GetConfigList()->begin(); for (int i = 0; i < this->clicked_row; i++) it++; - if (_game_mode == GM_NORMAL && ((this->slot == OWNER_DEITY) || Company::IsValidID(this->slot)) && (it->flags & SCRIPTCONFIG_INGAME) == 0) return; + if (_game_mode == GM_NORMAL && ((this->slot == OWNER_DEITY && !Game::GetInstance()->IsDead()) || (Company::IsValidAiID(this->slot) && !Company::Get(this->slot)->ai_instance->IsDead())) && (it->flags & SCRIPTCONFIG_INGAME) == 0) return; this->ai_config->SetSetting((*it).name, index); this->SetDirty(); } @@ -779,11 +779,11 @@ if (slot == OWNER_DEITY) return _game_mode != GM_NORMAL || Game::GetInstance() != NULL; if (_game_mode != GM_NORMAL) { - return slot > 0 && slot <= GetGameSettings().difficulty.max_no_competitors; + return slot >= 0 && slot <= MAX_COMPANIES - 1; } - if (Company::IsValidID(slot) || slot < 0) return false; + if (Company::IsValidHumanID(slot) || slot < 0) return false; - int max_slot = GetGameSettings().difficulty.max_no_competitors; + int max_slot = MAX_COMPANIES; for (CompanyID cid = COMPANY_FIRST; cid < (CompanyID)max_slot && cid < MAX_COMPANIES; cid++) { if (Company::IsValidHumanID(cid)) max_slot++; } @@ -802,7 +802,7 @@ } DrawString(r.left + 10, r.right - 10, r.top + WD_MATRIX_TOP, text, - (this->selected_slot == OWNER_DEITY) ? TC_WHITE : (IsEditable(OWNER_DEITY) ? TC_ORANGE : TC_SILVER)); + (this->selected_slot == OWNER_DEITY) ? TC_WHITE : (IsEditable(OWNER_DEITY) ? (_game_mode == GM_NORMAL) ? (Game::GetInstance()->IsDead()) ? TC_RED : TC_GREEN : TC_ORANGE : TC_SILVER)); break; } @@ -812,7 +812,7 @@ for (int i = this->vscroll->GetPosition(); this->vscroll->IsVisible(i) && i < MAX_COMPANIES; i++) { StringID text; - if ((_game_mode != GM_NORMAL && i == 0) || (_game_mode == GM_NORMAL && Company::IsValidHumanID(i))) { + if (_game_mode == GM_NORMAL && Company::IsValidHumanID(i)) { text = STR_AI_CONFIG_HUMAN_PLAYER; } else if (AIConfig::GetConfig((CompanyID)i)->GetInfo() != NULL) { SetDParamStr(0, AIConfig::GetConfig((CompanyID)i)->GetInfo()->GetName()); @@ -821,7 +821,7 @@ text = STR_AI_CONFIG_RANDOM_AI; } DrawString(r.left + 10, r.right - 10, y + WD_MATRIX_TOP, text, - (this->selected_slot == i) ? TC_WHITE : (IsEditable((CompanyID)i) ? TC_ORANGE : TC_SILVER)); + (this->selected_slot == i) ? TC_WHITE : (IsEditable((CompanyID)i) ? Company::IsValidAiID(i) ? Company::Get(i)->ai_instance->IsDead() ? TC_RED : TC_GREEN : TC_ORANGE : TC_SILVER)); y += this->line_height; } break; @@ -838,6 +838,12 @@ return; } + bool is_orange_slot = IsEditable(this->selected_slot) && !Company::IsValidAiID(this->selected_slot); + bool is_red_slot = IsEditable(this->selected_slot) && Company::IsValidAiID(this->selected_slot) && Company::Get(this->selected_slot)->ai_instance->IsDead(); + bool is_orange_slot_above = IsEditable((CompanyID)(this->selected_slot - 1)) && !Company::IsValidAiID(this->selected_slot - 1); + bool is_orange_slot_below = IsEditable((CompanyID)(this->selected_slot + 1)) && !Company::IsValidAiID(this->selected_slot + 1); + bool is_red_slot_above = IsEditable((CompanyID)(this->selected_slot - 1)) && Company::IsValidAiID(this->selected_slot - 1) && Company::Get(this->selected_slot - 1)->ai_instance->IsDead(); + bool is_red_slot_below = IsEditable((CompanyID)(this->selected_slot + 1)) && Company::IsValidAiID(this->selected_slot + 1) && Company::Get(this->selected_slot + 1)->ai_instance->IsDead(); switch (widget) { case WID_AIC_DECREASE: case WID_AIC_INCREASE: { @@ -845,7 +851,7 @@ if (widget == WID_AIC_DECREASE) { new_value = max(0, GetGameSettings().difficulty.max_no_competitors - 1); } else { - new_value = min(MAX_COMPANIES - 1, GetGameSettings().difficulty.max_no_competitors + 1); + new_value = min(MAX_COMPANIES, GetGameSettings().difficulty.max_no_competitors + 1); } IConsoleSetSetting("difficulty.max_no_competitors", new_value); this->InvalidateData(); @@ -867,7 +873,7 @@ } case WID_AIC_MOVE_UP: - if (IsEditable(this->selected_slot) && IsEditable((CompanyID)(this->selected_slot - 1))) { + if ((is_orange_slot || is_red_slot) && (is_orange_slot_above || is_red_slot_above)) { Swap(GetGameSettings().ai_config[this->selected_slot], GetGameSettings().ai_config[this->selected_slot - 1]); this->selected_slot--; this->vscroll->ScrollTowards(this->selected_slot); @@ -876,7 +882,7 @@ break; case WID_AIC_MOVE_DOWN: - if (IsEditable(this->selected_slot) && IsEditable((CompanyID)(this->selected_slot + 1))) { + if ((is_orange_slot || is_red_slot) && (is_orange_slot_below || is_red_slot_below)) { Swap(GetGameSettings().ai_config[this->selected_slot], GetGameSettings().ai_config[this->selected_slot + 1]); this->selected_slot++; this->vscroll->ScrollTowards(this->selected_slot); @@ -922,14 +928,32 @@ if (!gui_scope) return; this->SetWidgetDisabledState(WID_AIC_DECREASE, GetGameSettings().difficulty.max_no_competitors == 0); - this->SetWidgetDisabledState(WID_AIC_INCREASE, GetGameSettings().difficulty.max_no_competitors == MAX_COMPANIES - 1); - this->SetWidgetDisabledState(WID_AIC_CHANGE, (this->selected_slot == OWNER_DEITY && _game_mode == GM_NORMAL) || this->selected_slot == INVALID_COMPANY); - this->SetWidgetDisabledState(WID_AIC_CONFIGURE, this->selected_slot == INVALID_COMPANY || GetConfig(this->selected_slot)->GetConfigList()->size() == 0); - this->SetWidgetDisabledState(WID_AIC_MOVE_UP, this->selected_slot == OWNER_DEITY || this->selected_slot == INVALID_COMPANY || !IsEditable((CompanyID)(this->selected_slot - 1))); - this->SetWidgetDisabledState(WID_AIC_MOVE_DOWN, this->selected_slot == OWNER_DEITY || this->selected_slot == INVALID_COMPANY || !IsEditable((CompanyID)(this->selected_slot + 1))); + this->SetWidgetDisabledState(WID_AIC_INCREASE, GetGameSettings().difficulty.max_no_competitors == MAX_COMPANIES); + bool is_gs_slot = this->selected_slot == OWNER_DEITY; + bool invalid_slot = this->selected_slot == INVALID_COMPANY; + bool is_green_slot = Company::IsValidAiID(this->selected_slot) && !Company::Get(this->selected_slot)->ai_instance->IsDead(); + this->SetWidgetDisabledState(WID_AIC_CHANGE, invalid_slot || _game_mode == GM_NORMAL && (is_gs_slot || is_green_slot)); + this->SetWidgetDisabledState(WID_AIC_CONFIGURE, invalid_slot || GetConfig(this->selected_slot)->GetConfigList()->size() == 0); + + /* Display either Settings or Configure button */ + NWidgetCore *configure_button = this->GetWidget(WID_AIC_CONFIGURE); + if (_game_mode == GM_NORMAL && !invalid_slot && (is_gs_slot && !Game::GetInstance()->IsDead() || is_green_slot)) { + configure_button->SetDataTip(STR_AI_DEBUG_SETTINGS, STR_AI_DEBUG_SETTINGS_TOOLTIP); + } else { + configure_button->SetDataTip(STR_AI_CONFIG_CONFIGURE, STR_AI_CONFIG_CONFIGURE_TOOLTIP); + } + + bool is_silver_slot_above = !IsEditable((CompanyID)(this->selected_slot - 1)); + bool is_green_slot_above = Company::IsValidAiID(this->selected_slot - 1) && !Company::Get(this->selected_slot - 1)->ai_instance->IsDead(); + this->SetWidgetDisabledState(WID_AIC_MOVE_UP, is_gs_slot || invalid_slot || is_green_slot || is_silver_slot_above || is_green_slot_above); + + bool is_silver_slot_below = !IsEditable((CompanyID)(this->selected_slot + 1)); + bool is_green_slot_below = Company::IsValidAiID(this->selected_slot + 1) && !Company::Get(this->selected_slot + 1)->ai_instance->IsDead(); + this->SetWidgetDisabledState(WID_AIC_MOVE_DOWN, is_gs_slot || invalid_slot || is_green_slot || is_silver_slot_below || is_green_slot_below); + for (TextfileType tft = TFT_BEGIN; tft < TFT_END; tft++) { - this->SetWidgetDisabledState(WID_AIC_TEXTFILE + tft, this->selected_slot == INVALID_COMPANY || (GetConfig(this->selected_slot)->GetTextfile(tft, this->selected_slot) == NULL)); + this->SetWidgetDisabledState(WID_AIC_TEXTFILE + tft, invalid_slot || (GetConfig(this->selected_slot)->GetTextfile(tft, this->selected_slot) == NULL)); } } }; @@ -1375,6 +1399,15 @@ this->SetWidgetLoweredState(WID_AID_MATCH_CASE_BTN, this->case_sensitive_break_check); this->SetWidgetDisabledState(WID_AID_SETTINGS, ai_debug_company == INVALID_COMPANY); + + /* Display either Settings or Configure button */ + NWidgetCore *settings_button = this->GetWidget(WID_AID_SETTINGS); + if (ai_debug_company == INVALID_COMPANY || (ai_debug_company == OWNER_DEITY && !Game::GetInstance()->IsDead() || Company::IsValidAiID(this->ai_debug_company) && !Company::Get(this->ai_debug_company)->ai_instance->IsDead())) { + settings_button->SetDataTip(STR_AI_DEBUG_SETTINGS, STR_AI_DEBUG_SETTINGS_TOOLTIP); + } else { + settings_button->SetDataTip(STR_AI_CONFIG_CONFIGURE, STR_AI_CONFIG_CONFIGURE_TOOLTIP); + } + this->SetWidgetDisabledState(WID_AID_RELOAD_TOGGLE, ai_debug_company == INVALID_COMPANY || ai_debug_company == OWNER_DEITY); this->SetWidgetDisabledState(WID_AID_CONTINUE_BTN, ai_debug_company == INVALID_COMPANY || (ai_debug_company == OWNER_DEITY ? !Game::IsPaused() : !AI::IsPaused(ai_debug_company))); Index: src/ai/ai_instance.cpp =================================================================== --- src/ai/ai_instance.cpp (revision 27550) +++ src/ai/ai_instance.cpp (working copy) @@ -81,6 +81,7 @@ #include "../company_base.h" #include "../company_func.h" +#include "../window_func.h" #include "../safeguards.h" @@ -214,6 +215,7 @@ ScriptInstance::Died(); ShowAIDebugWindow(_current_company); + InvalidateWindowData(WC_GAME_OPTIONS, WN_GAME_OPTIONS_AI); const AIInfo *info = AIConfig::GetConfig(_current_company, AIConfig::SSS_FORCE_GAME)->GetInfo(); if (info != NULL) { Index: src/game/game_instance.cpp =================================================================== --- src/game/game_instance.cpp (revision 27550) +++ src/game/game_instance.cpp (working copy) @@ -85,6 +85,8 @@ #include "../script/api/game/game_waypointlist.hpp.sq" #include "../script/api/game/game_window.hpp.sq" +#include "../window_func.h" + #include "../safeguards.h" @@ -232,6 +234,7 @@ ScriptInstance::Died(); ShowAIDebugWindow(OWNER_DEITY); + InvalidateWindowData(WC_GAME_OPTIONS, WN_GAME_OPTIONS_AI); const GameInfo *info = Game::GetInfo(); if (info != NULL) { Index: src/lang/english.txt =================================================================== --- src/lang/english.txt (revision 27550) +++ src/lang/english.txt (working copy) @@ -3979,10 +3979,10 @@ STR_ERROR_AI_DEBUG_SERVER_ONLY :{YELLOW}AI/Game Script Debug window is only available for the server # AI configuration window -STR_AI_CONFIG_CAPTION :{WHITE}AI/Game Script Configuration -STR_AI_CONFIG_GAMELIST_TOOLTIP :{BLACK}The Game Script that will be loaded in the next game -STR_AI_CONFIG_AILIST_TOOLTIP :{BLACK}The AIs that will be loaded in the next game -STR_AI_CONFIG_HUMAN_PLAYER :Human player +STR_AI_CONFIG_CAPTION :{WHITE}AI/Game Script Settings +STR_AI_CONFIG_GAMELIST_TOOLTIP :{BLACK}The Game Script that is loaded or will be loaded in the next game +STR_AI_CONFIG_AILIST_TOOLTIP :{BLACK}The AIs that are currently loaded or will be loaded next time they start on these Company IDs while in a game +STR_AI_CONFIG_HUMAN_PLAYER :Human Company STR_AI_CONFIG_RANDOM_AI :Random AI STR_AI_CONFIG_NONE :(none) Index: src/table/settings.ini =================================================================== --- src/table/settings.ini (revision 27550) +++ src/table/settings.ini (working copy) @@ -103,7 +103,7 @@ from = 97 def = 0 min = 0 -max = MAX_COMPANIES - 1 +max = MAX_COMPANIES interval = 1 proc = MaxNoAIsChange cat = SC_BASIC