Loading

Paste #powbjkea0

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

Comments