Loading

Paste #pwvo7pr2m

  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.  
  8.     AIConfigWindow() : Window(&_ai_config_desc)
  9.     {
  10.         this->InitNested(WN_GAME_OPTIONS_AI); // Initializes 'this->line_height' as a side effect.
  11.         this->selected_slot = INVALID_COMPANY;
  12.         this->OnInvalidateData(0);
  13.     }
  14.  
  15.     ~AIConfigWindow()
  16.     {
  17.         DeleteWindowByClass(WC_AI_LIST);
  18.         if (_game_mode != GM_NORMAL) DeleteWindowByClass(WC_AI_SETTINGS);
  19.     }
  20.  
  21.     virtual void SetStringParameters(int widget) const
  22.     {
  23.         switch (widget) {
  24.             case WID_AIC_CAPTION:
  25.                 SetDParam(0, (_game_mode != GM_NORMAL) ? STR_AI_CONFIG_CAPTION : STR_AI_CONFIG_CAPTION_INGAME);
  26.                 break;
  27.             case WID_AIC_NUMBER:
  28.                 SetDParam(0, GetGameSettings().difficulty.max_no_competitors);
  29.                 break;
  30.             case WID_AIC_CHANGE:
  31.                 switch (selected_slot) {
  32.                     case OWNER_DEITY:
  33.                         SetDParam(0, STR_AI_CONFIG_CHANGE_GAMESCRIPT);
  34.                         break;
  35.  
  36.                     case INVALID_COMPANY:
  37.                         SetDParam(0, STR_AI_CONFIG_CHANGE_NONE);
  38.                         break;
  39.  
  40.                     default:
  41.                         SetDParam(0, STR_AI_CONFIG_CHANGE_AI);
  42.                         break;
  43.                 }
  44.                 break;
  45.         }
  46.     }
  47.  
  48.     virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
  49.     {
  50.         switch (widget) {
  51.             case WID_AIC_GAMELIST: {
  52.                 this->line_height = max((uint)FONT_HEIGHT_NORMAL, GetSpriteSize(SPR_SQUARE).height) + WD_MATRIX_TOP + WD_MATRIX_BOTTOM;
  53.                 size->height = 1 * this->line_height;
  54.                 break;
  55.             }
  56.  
  57.             case WID_AIC_LIST: {
  58.                
  59.                 this->line_height = max((uint)FONT_HEIGHT_NORMAL, GetSpriteSize(SPR_SQUARE).height) + WD_MATRIX_TOP + WD_MATRIX_BOTTOM;
  60.                 size->height = 15 * this->line_height;
  61.                 break;
  62.             }
  63.  
  64.             case WID_AIC_CHANGE: {
  65.                 size->width = max(GetStringBoundingBox(STR_AI_CONFIG_CHANGE).width + GetStringBoundingBox(STR_AI_CONFIG_CHANGE_GAMESCRIPT).width,
  66.                     max(GetStringBoundingBox(STR_AI_CONFIG_CHANGE).width + GetStringBoundingBox(STR_AI_CONFIG_CHANGE_NONE).width,
  67.                         GetStringBoundingBox(STR_AI_CONFIG_CHANGE).width + GetStringBoundingBox(STR_AI_CONFIG_CHANGE_AI).width));
  68.                 break;
  69.             }
  70.  
  71.             case WID_AIC_CONFIGURE: {
  72.                 size->width = max(GetStringBoundingBox(STR_AI_CONFIG_CONFIGURE).width, GetStringBoundingBox(STR_AI_DEBUG_SETTINGS).width);
  73.                 break;
  74.             }
  75.         }
  76.     }
  77.  
  78.     /**
  79.      * Can the AI config in the given company slot be edited?
  80.      * @param slot The slot to query.
  81.      * @return True if and only if the given AI Config slot can e edited.
  82.      */
  83.     static bool IsEditable(CompanyID slot)
  84.     {
  85.         if (slot == OWNER_DEITY) return _game_mode != GM_NORMAL || Game::GetInstance() != NULL;
  86.  
  87.         if (_game_mode != GM_NORMAL) {
  88.             return slot >= 0 && slot < MAX_COMPANIES;
  89.         }
  90.         if (Company::IsValidHumanID(slot) || slot < 0) return false;
  91.  
  92.         return slot < MAX_COMPANIES;
  93.     }
  94.  
  95.     virtual void DrawWidget(const Rect &r, int widget) const
  96.     {
  97.         switch (widget) {
  98.             case WID_AIC_GAMELIST: {
  99.                 uint widest_cid = 0;
  100.                 for (CompanyID i = COMPANY_FIRST; i < MAX_COMPANIES; i++) {
  101.                     SetDParam(0, i + 1);
  102.                     widest_cid = max(GetStringBoundingBox(STR_JUST_INT).width, widest_cid);
  103.                 }
  104.  
  105.                 Dimension square = GetSpriteSize(SPR_SQUARE);
  106.                 uint square_y_offset = (line_height - square.height) / 2;
  107.  
  108.                 StringID text = STR_AI_CONFIG_NONE;
  109.                 if (GameConfig::GetConfig()->GetInfo() != NULL) {
  110.                     SetDParamStr(0, GameConfig::GetConfig()->GetInfo()->GetName());
  111.                     text = STR_JUST_RAW_STRING;
  112.                 }
  113.  
  114.                 DrawSprite(SPR_SQUARE,
  115.                     IsEditable(OWNER_DEITY) ? (_game_mode == GM_NORMAL) ? (IsDead(OWNER_DEITY)) ? PALETTE_TO_RED : PALETTE_TO_GREEN : PALETTE_TO_BLUE : PALETTE_TO_GREY,
  116.                         r.left + WD_MATRIX_LEFT, r.top + square_y_offset);
  117.                 DrawString(r.left + WD_MATRIX_LEFT + square.width + WD_MATRIX_LEFT + widest_cid + WD_MATRIX_LEFT, r.right - WD_MATRIX_RIGHT, r.top + WD_MATRIX_TOP, text,
  118.                         (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));
  119.  
  120.                 break;
  121.             }
  122.  
  123.             case WID_AIC_LIST: {
  124.                 int y = r.top;
  125.  
  126.                 uint widest_cid = 0;
  127.                 for (CompanyID i = COMPANY_FIRST; i < MAX_COMPANIES; i++) {
  128.                     SetDParam(0, i + 1);
  129.                     widest_cid = max(GetStringBoundingBox(STR_JUST_INT).width, widest_cid);
  130.                 }
  131.  
  132.                 Dimension square = GetSpriteSize(SPR_SQUARE);
  133.                 uint square_y_offset = (line_height - square.height) / 2;
  134.  
  135.                 StringID rai = STR_AI_CONFIG_RANDOM_AI;
  136.                 uint rai_width = GetStringBoundingBox(rai).width;
  137.  
  138.                 for (CompanyID i = COMPANY_FIRST; i < MAX_COMPANIES; i++) {
  139.                     SetDParam(0, i + 1);
  140.                     StringID cid = STR_JUST_INT;
  141.                     DrawString(r.left + WD_MATRIX_LEFT + square.width, r.left + WD_MATRIX_LEFT + square.width + widest_cid, y + WD_MATRIX_TOP, cid, TC_LIGHT_BLUE, SA_RIGHT);
  142.  
  143.                     StringID text;
  144.                     if (_game_mode == GM_NORMAL && Company::IsValidHumanID(i)) {
  145.                         text = STR_AI_CONFIG_HUMAN_PLAYER;
  146.                     } else if (AIConfig::GetConfig((CompanyID)i)->GetInfo() != NULL) {
  147.                         SetDParamStr(0, AIConfig::GetConfig((CompanyID)i)->GetInfo()->GetName());
  148.                         text = STR_JUST_RAW_STRING;
  149.                     } else {
  150.                         text = rai;
  151.                     }
  152.                     uint text_width = GetStringBoundingBox(text).width;
  153.                    
  154.                     DrawSprite(SPR_SQUARE,
  155.                         IsEditable((CompanyID)i) ? Company::IsValidAiID(i) ? IsDead((CompanyID)i) ? PALETTE_TO_RED : PALETTE_TO_GREEN : _game_mode != GM_NORMAL ? PALETTE_TO_BLUE : PALETTE_TO_ORANGE : PALETTE_TO_GREY,
  156.                             r.left + WD_MATRIX_LEFT, y + square_y_offset);
  157.  
  158.                     DrawString(r.left + WD_MATRIX_LEFT + square.width + WD_MATRIX_LEFT + widest_cid + WD_MATRIX_LEFT, r.right - WD_MATRIX_RIGHT - rai_width - WD_MATRIX_RIGHT, y + WD_MATRIX_TOP, text,
  159.                         (this->selected_slot == i) ? TC_WHITE : (IsEditable((CompanyID)i) ? Company::IsValidAiID(i) ? IsDead((CompanyID)i) ? TC_RED : TC_GREEN : TC_ORANGE : TC_SILVER));
  160.  
  161.                     if (_game_mode == GM_NORMAL && Company::IsValidAiID(i) && AIConfig::GetConfig((CompanyID)i)->IsRandom()) {
  162.                         DrawString(min(r.left + WD_MATRIX_LEFT + square.width + WD_MATRIX_LEFT + widest_cid + WD_MATRIX_LEFT, r.right - WD_MATRIX_RIGHT - rai_width - WD_MATRIX_RIGHT), r.right - WD_MATRIX_RIGHT, y + WD_MATRIX_TOP, rai,
  163.                             (this->selected_slot == i) ? TC_WHITE : (IsEditable((CompanyID)i) ? Company::IsValidAiID(i) ? IsDead((CompanyID)i) ? TC_RED : TC_GREEN : TC_ORANGE : TC_SILVER), SA_RIGHT);
  164.                     }
  165.                     y += this->line_height;
  166.                 }
  167.                 break;
  168.             }
  169.         }
  170.     }
  171.  
  172.     virtual void OnClick(Point pt, int widget, int click_count)
  173.     {
  174.         if (widget >= WID_AIC_TEXTFILE && widget < WID_AIC_TEXTFILE + TFT_END) {
  175.             if (this->selected_slot == INVALID_COMPANY || GetConfig(this->selected_slot) == NULL) return;
  176.  
  177.             ShowScriptTextfileWindow((TextfileType)(widget - WID_AIC_TEXTFILE), this->selected_slot);
  178.             return;
  179.         }
  180.  
  181.         switch (widget) {
  182.             case WID_AIC_DECREASE:
  183.             case WID_AIC_INCREASE: {
  184.                 int new_value;
  185.                 if (widget == WID_AIC_DECREASE) {
  186.                     new_value = max(0, GetGameSettings().difficulty.max_no_competitors - 1);
  187.                 } else {
  188.                     new_value = min(MAX_COMPANIES, GetGameSettings().difficulty.max_no_competitors + 1);
  189.                 }
  190.                 IConsoleSetSetting("difficulty.max_no_competitors", new_value);
  191.                 this->InvalidateData();
  192.                 break;
  193.             }
  194.  
  195.             case WID_AIC_GAMELIST: {
  196.                 this->selected_slot = OWNER_DEITY;
  197.                 this->InvalidateData();
  198.                 if (click_count > 1 && this->selected_slot != INVALID_COMPANY && _game_mode != GM_NORMAL) ShowAIListWindow((CompanyID)this->selected_slot);
  199.                 break;
  200.             }
  201.  
  202.             case WID_AIC_LIST: { // Select a slot
  203.                 this->selected_slot = (CompanyID)this->GetRowFromWidget(pt.y, widget, 0, this->line_height);
  204.                 this->InvalidateData();
  205.                 if (click_count > 1 && this->selected_slot != INVALID_COMPANY) ShowAIListWindow((CompanyID)this->selected_slot);
  206.                 break;
  207.             }
  208.  
  209.             case WID_AIC_MOVE_UP:
  210.                 if (IsEditable(this->selected_slot) && IsDead(this->selected_slot) && IsEditable((CompanyID)(this->selected_slot - 1)) && IsDead((CompanyID)(this->selected_slot - 1))) {
  211.                     Swap(GetGameSettings().ai_config[this->selected_slot], GetGameSettings().ai_config[this->selected_slot - 1]);
  212.                     this->selected_slot--;
  213.                     this->InvalidateData();
  214.                 }
  215.                 break;
  216.  
  217.             case WID_AIC_MOVE_DOWN:
  218.                 if (IsEditable(this->selected_slot) && IsDead(this->selected_slot) && IsEditable((CompanyID)(this->selected_slot + 1)) && IsDead((CompanyID)(this->selected_slot + 1))) {
  219.                     Swap(GetGameSettings().ai_config[this->selected_slot], GetGameSettings().ai_config[this->selected_slot + 1]);
  220.                     this->selected_slot++;
  221.                     this->InvalidateData();
  222.                 }
  223.                 break;
  224.  
  225.             case WID_AIC_CHANGE:  // choose other AI
  226.                 ShowAIListWindow((CompanyID)this->selected_slot);
  227.                 break;
  228.  
  229.             case WID_AIC_CONFIGURE: // change the settings for an AI
  230.                 ShowAISettingsWindow((CompanyID)this->selected_slot);
  231.                 break;
  232.  
  233.             case WID_AIC_CLOSE:
  234.                 delete this;
  235.                 break;
  236.  
  237.             case WID_AIC_CONTENT_DOWNLOAD:
  238.                 if (!_network_available) {
  239.                     ShowErrorMessage(STR_NETWORK_ERROR_NOTAVAILABLE, INVALID_STRING_ID, WL_ERROR);
  240.                 } else {
  241. #if defined(ENABLE_NETWORK)
  242.                     ShowNetworkContentListWindow(NULL, CONTENT_TYPE_AI, CONTENT_TYPE_GAME);
  243. #endif
  244.                 }
  245.                 break;
  246.         }
  247.     }
  248.  
  249.     /**
  250.      * Some data on this window has become invalid.
  251.      * @param data Information about the changed data.
  252.      * @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.
  253.      */
  254.     virtual void OnInvalidateData(int data = 0, bool gui_scope = true)
  255.     {
  256.         if (!IsEditable(this->selected_slot)) {
  257.             this->selected_slot = INVALID_COMPANY;
  258.         }
  259.  
  260.         if (!gui_scope) return;
  261.  
  262.         this->SetWidgetDisabledState(WID_AIC_DECREASE, GetGameSettings().difficulty.max_no_competitors == 0);
  263.         this->SetWidgetDisabledState(WID_AIC_INCREASE, GetGameSettings().difficulty.max_no_competitors == MAX_COMPANIES);
  264.         this->SetWidgetDisabledState(WID_AIC_CHANGE, this->selected_slot == INVALID_COMPANY || _game_mode == GM_NORMAL && (this->selected_slot == OWNER_DEITY || !IsDead(this->selected_slot)));
  265.         this->SetWidgetDisabledState(WID_AIC_CONFIGURE, this->selected_slot == INVALID_COMPANY || GetConfig(this->selected_slot)->GetConfigList()->size() == 0);
  266.  
  267.         /* Display either Settings or Configure button */
  268.         NWidgetCore *configure_button = this->GetWidget<NWidgetCore>(WID_AIC_CONFIGURE);
  269.         if (_game_mode == GM_NORMAL && this->selected_slot != INVALID_COMPANY && !IsDead(this->selected_slot)) {
  270.             configure_button->SetDataTip(STR_AI_DEBUG_SETTINGS, STR_AI_DEBUG_SETTINGS_TOOLTIP);
  271.         } else {
  272.             configure_button->SetDataTip(STR_AI_CONFIG_CONFIGURE, STR_AI_CONFIG_CONFIGURE_TOOLTIP);
  273.         }
  274.  
  275.         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)));
  276.         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)));
  277.  
  278.         for (TextfileType tft = TFT_BEGIN; tft < TFT_END; tft++) {
  279.             this->SetWidgetDisabledState(WID_AIC_TEXTFILE + tft, this->selected_slot == INVALID_COMPANY || (GetConfig(this->selected_slot)->GetTextfile(tft, this->selected_slot) == NULL));
  280.         }
  281.     }
  282. };

Comments