| | 1 | /**
|
---|
| | 2 | * Window to configure which AIs will start.
|
---|
| | 3 | */
|
---|
| | 4 | struct AIConfigWindow : public Window {
|
---|
| | 5 | CompanyID selected_slot; ///< The currently selected AI slot or \c INVALID_COMPANY.
|
---|
| | 6 | int line_height; ///< Height of a single AI-name line.
|
---|
| | 7 | uint cid_width; ///< Width of Company # string.
|
---|
| | 8 |
|
---|
| | 9 | AIConfigWindow() : Window(&_ai_config_desc)
|
---|
| | 10 | {
|
---|
| | 11 | this->InitNested(WN_GAME_OPTIONS_AI); // Initializes 'this->line_height' as a side effect.
|
---|
| | 12 | this->selected_slot = INVALID_COMPANY;
|
---|
| | 13 | this->OnInvalidateData(0);
|
---|
| | 14 | }
|
---|
| | 15 |
|
---|
| | 16 | ~AIConfigWindow()
|
---|
| | 17 | {
|
---|
| | 18 | DeleteWindowByClass(WC_AI_LIST);
|
---|
| | 19 | if (_game_mode != GM_NORMAL) DeleteWindowByClass(WC_AI_SETTINGS);
|
---|
| | 20 | }
|
---|
| | 21 |
|
---|
| | 22 | virtual void SetStringParameters(int widget) const
|
---|
| | 23 | {
|
---|
| | 24 | switch (widget) {
|
---|
| | 25 | case WID_AIC_CAPTION:
|
---|
| | 26 | SetDParam(0, (_game_mode != GM_NORMAL) ? STR_AI_CONFIG_CAPTION : STR_AI_CONFIG_CAPTION_INGAME);
|
---|
| | 27 | break;
|
---|
| | 28 | case WID_AIC_NUMBER:
|
---|
| | 29 | SetDParam(0, GetGameSettings().difficulty.max_no_competitors);
|
---|
| | 30 | break;
|
---|
| | 31 | case WID_AIC_CHANGE:
|
---|
| | 32 | switch (selected_slot) {
|
---|
| | 33 | case OWNER_DEITY:
|
---|
| | 34 | SetDParam(0, STR_AI_CONFIG_CHANGE_GAMESCRIPT);
|
---|
| | 35 | break;
|
---|
| | 36 |
|
---|
| | 37 | case INVALID_COMPANY:
|
---|
| | 38 | SetDParam(0, STR_AI_CONFIG_CHANGE_NONE);
|
---|
| | 39 | break;
|
---|
| | 40 |
|
---|
| | 41 | default:
|
---|
| | 42 | SetDParam(0, STR_AI_CONFIG_CHANGE_AI);
|
---|
| | 43 | break;
|
---|
| | 44 | }
|
---|
| | 45 | break;
|
---|
| | 46 | }
|
---|
| | 47 | }
|
---|
| | 48 |
|
---|
| | 49 | virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
|
---|
| | 50 | {
|
---|
| | 51 | switch (widget) {
|
---|
| | 52 | case WID_AIC_GAMELIST:
|
---|
| | 53 | this->line_height = FONT_HEIGHT_NORMAL + WD_MATRIX_TOP + WD_MATRIX_BOTTOM;
|
---|
| | 54 | size->height = 1 * this->line_height;
|
---|
5 | } | 58 | }
|
---|
| | 59 | break;
|
---|
| | 60 |
|
---|
| | 61 | case WID_AIC_LIST:
|
---|
| | 62 | this->line_height = FONT_HEIGHT_NORMAL + WD_MATRIX_TOP + WD_MATRIX_BOTTOM;
|
---|
| | 63 | size->height = 15 * this->line_height;
|
---|
| | 64 | break;
|
---|
| | 65 | }
|
---|
| | 66 | }
|
---|
| | 67 |
|
---|
| | 68 | /**
|
---|
| | 69 | * Can the AI config in the given company slot be edited?
|
---|
| | 70 | * @param slot The slot to query.
|
---|
| | 71 | * @return True if and only if the given AI Config slot can e edited.
|
---|
| | 72 | */
|
---|
| | 73 | static bool IsEditable(CompanyID slot)
|
---|
| | 74 | {
|
---|
| | 75 | if (slot == OWNER_DEITY) return _game_mode != GM_NORMAL || Game::GetInstance() != NULL;
|
---|
| | 76 |
|
---|
| | 77 | if (_game_mode != GM_NORMAL) {
|
---|
| | 78 | return slot >= 0 && slot < MAX_COMPANIES;
|
---|
| | 79 | }
|
---|
| | 80 | if (Company::IsValidHumanID(slot) || slot < 0) return false;
|
---|
| | 81 |
|
---|
| | 82 | return slot < MAX_COMPANIES;
|
---|
| | 83 | }
|
---|
| | 84 |
|
---|
| | 85 | virtual void DrawWidget(const Rect &r, int widget) const
|
---|
| | 86 | {
|
---|
| | 87 | switch (widget) {
|
---|
| | 88 | case WID_AIC_GAMELIST: {
|
---|
| | 89 | StringID text = STR_AI_CONFIG_NONE;
|
---|
| | 90 |
|
---|
| | 91 | if (GameConfig::GetConfig()->GetInfo() != NULL) {
|
---|
| | 92 | SetDParamStr(0, GameConfig::GetConfig()->GetInfo()->GetName());
|
---|
| | 93 | text = STR_JUST_RAW_STRING;
|
---|
| | 94 | }
|
---|
| | 95 |
|
---|
| | 96 | DrawString(r.left + 10, r.right - 10, r.top + WD_MATRIX_TOP, text,
|
---|
| | 97 | (this->selected_slot == OWNER_DEITY) ? TC_WHITE : (IsEditable(OWNER_DEITY) ? (_game_mode == GM_NORMAL) ? (IsDead(OWNER_DEITY)) ? TC_RED : TC_GREEN : TC_ORANGE : TC_SILVER));
|
---|
| | 98 |
|
---|
| | 99 | break;
|
---|
| | 100 | }
|
---|
| | 101 |
|
---|
| | 102 | case WID_AIC_LIST: {
|
---|
| | 103 | int y = r.top;
|
---|
| | 104 | for (CompanyID i = COMPANY_FIRST; i < MAX_COMPANIES; i++) {
|
---|
| | 105 | StringID cid = STR_AI_CONFIG_AILIST_COMPANY_ID_1 + i;
|
---|
| | 106 | DrawString(r.left + 10, r.left + 90, y + WD_MATRIX_TOP, cid);
|
---|
| | 107 | StringID text;
|
---|
| | 108 |
|
---|
| | 109 | if (_game_mode == GM_NORMAL && Company::IsValidHumanID(i)) {
|
---|
| | 110 | text = STR_AI_CONFIG_HUMAN_PLAYER;
|
---|
| | 111 | } else if (AIConfig::GetConfig((CompanyID)i)->GetInfo() != NULL) {
|
---|
| | 112 | SetDParamStr(0, AIConfig::GetConfig((CompanyID)i)->GetInfo()->GetName());
|
---|
| | 113 | text = STR_JUST_RAW_STRING;
|
---|
| | 114 | } else {
|
---|
| | 115 | text = STR_AI_CONFIG_RANDOM_AI;
|
---|
| | 116 | }
|
---|
| | 117 | DrawString(r.left + 10 + 90, r.right - 10, y + WD_MATRIX_TOP, text,
|
---|
| | 118 | (this->selected_slot == i) ? TC_WHITE : (IsEditable((CompanyID)i) ? Company::IsValidAiID(i) ? IsDead((CompanyID)i) ? TC_RED : TC_GREEN : TC_ORANGE : TC_SILVER));
|
---|
| | 119 | y += this->line_height;
|
---|
| | 120 | }
|
---|
| | 121 | break;
|
---|
| | 122 | }
|
---|
| | 123 | }
|
---|
| | 124 | }
|
---|
| | 125 |
|
---|
| | 126 | virtual void OnClick(Point pt, int widget, int click_count)
|
---|
| | 127 | {
|
---|
| | 128 | if (widget >= WID_AIC_TEXTFILE && widget < WID_AIC_TEXTFILE + TFT_END) {
|
---|
| | 129 | if (this->selected_slot == INVALID_COMPANY || GetConfig(this->selected_slot) == NULL) return;
|
---|
| | 130 |
|
---|
| | 131 | ShowScriptTextfileWindow((TextfileType)(widget - WID_AIC_TEXTFILE), this->selected_slot);
|
---|
| | 132 | return;
|
---|
| | 133 | }
|
---|
| | 134 |
|
---|
| | 135 | switch (widget) {
|
---|
| | 136 | case WID_AIC_DECREASE:
|
---|
| | 137 | case WID_AIC_INCREASE: {
|
---|
| | 138 | int new_value;
|
---|
| | 139 | if (widget == WID_AIC_DECREASE) {
|
---|
| | 140 | new_value = max(0, GetGameSettings().difficulty.max_no_competitors - 1);
|
---|
| | 141 | } else {
|
---|
| | 142 | new_value = min(MAX_COMPANIES, GetGameSettings().difficulty.max_no_competitors + 1);
|
---|
| | 143 | }
|
---|
| | 144 | IConsoleSetSetting("difficulty.max_no_competitors", new_value);
|
---|
| | 145 | this->InvalidateData();
|
---|
| | 146 | break;
|
---|
| | 147 | }
|
---|
| | 148 |
|
---|
| | 149 | case WID_AIC_GAMELIST: {
|
---|
| | 150 | this->selected_slot = OWNER_DEITY;
|
---|
| | 151 | this->InvalidateData();
|
---|
| | 152 | if (click_count > 1 && this->selected_slot != INVALID_COMPANY && _game_mode != GM_NORMAL) ShowAIListWindow((CompanyID)this->selected_slot);
|
---|
| | 153 | break;
|
---|
| | 154 | }
|
---|
| | 155 |
|
---|
| | 156 | case WID_AIC_LIST: { // Select a slot
|
---|
| | 157 | this->selected_slot = (CompanyID)this->GetRowFromWidget(pt.y, widget, 0, this->line_height);
|
---|
| | 158 | this->InvalidateData();
|
---|
| | 159 | if (click_count > 1 && this->selected_slot != INVALID_COMPANY) ShowAIListWindow((CompanyID)this->selected_slot);
|
---|
| | 160 | break;
|
---|
| | 161 | }
|
---|
| | 162 |
|
---|
| | 163 | case WID_AIC_MOVE_UP:
|
---|
| | 164 | if (IsEditable(this->selected_slot) && IsDead(this->selected_slot) && IsEditable((CompanyID)(this->selected_slot - 1)) && IsDead((CompanyID)(this->selected_slot - 1))) {
|
---|
| | 165 | Swap(GetGameSettings().ai_config[this->selected_slot], GetGameSettings().ai_config[this->selected_slot - 1]);
|
---|
| | 166 | this->selected_slot--;
|
---|
| | 167 | this->InvalidateData();
|
---|
| | 168 | }
|
---|
| | 169 | break;
|
---|
| | 170 |
|
---|
| | 171 | case WID_AIC_MOVE_DOWN:
|
---|
| | 172 | if (IsEditable(this->selected_slot) && IsDead(this->selected_slot) && IsEditable((CompanyID)(this->selected_slot + 1)) && IsDead((CompanyID)(this->selected_slot + 1))) {
|
---|
| | 173 | Swap(GetGameSettings().ai_config[this->selected_slot], GetGameSettings().ai_config[this->selected_slot + 1]);
|
---|
| | 174 | this->selected_slot++;
|
---|
| | 175 | this->InvalidateData();
|
---|
| | 176 | }
|
---|
| | 177 | break;
|
---|
| | 178 |
|
---|
| | 179 | case WID_AIC_CHANGE: // choose other AI
|
---|
| | 180 | ShowAIListWindow((CompanyID)this->selected_slot);
|
---|
| | 181 | break;
|
---|
| | 182 |
|
---|
| | 183 | case WID_AIC_CONFIGURE: // change the settings for an AI
|
---|
| | 184 | ShowAISettingsWindow((CompanyID)this->selected_slot);
|
---|
| | 185 | break;
|
---|
| | 186 |
|
---|
| | 187 | case WID_AIC_CLOSE:
|
---|
| | 188 | delete this;
|
---|
| | 189 | break;
|
---|
| | 190 |
|
---|
| | 191 | case WID_AIC_CONTENT_DOWNLOAD:
|
---|
| | 192 | if (!_network_available) {
|
---|
| | 193 | ShowErrorMessage(STR_NETWORK_ERROR_NOTAVAILABLE, INVALID_STRING_ID, WL_ERROR);
|
---|
| | 194 | } else {
|
---|
| | 195 | #if defined(ENABLE_NETWORK)
|
---|
| | 196 | ShowNetworkContentListWindow(NULL, CONTENT_TYPE_AI, CONTENT_TYPE_GAME);
|
---|
| | 197 | #endif
|
---|
| | 198 | }
|
---|
| | 199 | break;
|
---|
| | 200 | }
|
---|
| | 201 | }
|
---|
| | 202 |
|
---|
| | 203 | /**
|
---|
| | 204 | * Some data on this window has become invalid.
|
---|
| | 205 | * @param data Information about the changed data.
|
---|
| | 206 | * @param gui_scope Whether the call is done from GUI scope. You may not do everything when not in GUI scope. See #InvalidateWindowData() for details.
|
---|
| | 207 | */
|
---|
| | 208 | virtual void OnInvalidateData(int data = 0, bool gui_scope = true)
|
---|
| | 209 | {
|
---|
| | 210 | if (!IsEditable(this->selected_slot)) {
|
---|
| | 211 | this->selected_slot = INVALID_COMPANY;
|
---|
| | 212 | }
|
---|
| | 213 |
|
---|
| | 214 | if (!gui_scope) return;
|
---|
| | 215 |
|
---|
| | 216 | this->SetWidgetDisabledState(WID_AIC_DECREASE, GetGameSettings().difficulty.max_no_competitors == 0);
|
---|
| | 217 | this->SetWidgetDisabledState(WID_AIC_INCREASE, GetGameSettings().difficulty.max_no_competitors == MAX_COMPANIES);
|
---|
| | 218 | this->SetWidgetDisabledState(WID_AIC_CHANGE, this->selected_slot == INVALID_COMPANY || _game_mode == GM_NORMAL && (this->selected_slot == OWNER_DEITY || !IsDead(this->selected_slot)));
|
---|
| | 219 | this->SetWidgetDisabledState(WID_AIC_CONFIGURE, this->selected_slot == INVALID_COMPANY || GetConfig(this->selected_slot)->GetConfigList()->size() == 0);
|
---|
| | 220 |
|
---|
| | 221 | /* Display either Settings or Configure button */
|
---|
| | 222 | NWidgetCore *configure_button = this->GetWidget<NWidgetCore>(WID_AIC_CONFIGURE);
|
---|
| | 223 | if (_game_mode == GM_NORMAL && this->selected_slot != INVALID_COMPANY && !IsDead(this->selected_slot)) {
|
---|
| | 224 | configure_button->SetDataTip(STR_AI_DEBUG_SETTINGS, STR_AI_DEBUG_SETTINGS_TOOLTIP);
|
---|
| | 225 | } else {
|
---|
| | 226 | configure_button->SetDataTip(STR_AI_CONFIG_CONFIGURE, STR_AI_CONFIG_CONFIGURE_TOOLTIP);
|
---|
| | 227 | }
|
---|
| | 228 |
|
---|
| | 229 | this->SetWidgetDisabledState(WID_AIC_MOVE_UP, this->selected_slot == INVALID_COMPANY || this->selected_slot == OWNER_DEITY || !IsDead(this->selected_slot) || !IsEditable((CompanyID)(this->selected_slot - 1)) || !IsDead((CompanyID)(this->selected_slot - 1)));
|
---|
| | 230 | this->SetWidgetDisabledState(WID_AIC_MOVE_DOWN, this->selected_slot == INVALID_COMPANY || this->selected_slot == OWNER_DEITY || !IsDead(this->selected_slot) || !IsEditable((CompanyID)(this->selected_slot + 1)) || !IsDead((CompanyID)(this->selected_slot + 1)));
|
---|
| | 231 |
|
---|
| | 232 | for (TextfileType tft = TFT_BEGIN; tft < TFT_END; tft++) {
|
---|
| | 233 | this->SetWidgetDisabledState(WID_AIC_TEXTFILE + tft, this->selected_slot == INVALID_COMPANY || (GetConfig(this->selected_slot)->GetTextfile(tft, this->selected_slot) == NULL));
|
---|
| | 234 | }
|
---|
| | 235 | }
|
---|
| | 236 | }; |
---|