ai_gui.cpp

Go to the documentation of this file.
00001 /* $Id: ai_gui.cpp 15428 2009-02-09 02:57:15Z rubidium $ */
00002 
00005 #include "../stdafx.h"
00006 #include "../gui.h"
00007 #include "../window_gui.h"
00008 #include "../company_func.h"
00009 #include "../company_base.h"
00010 #include "../company_gui.h"
00011 #include "../strings_func.h"
00012 #include "../window_func.h"
00013 #include "../gfx_func.h"
00014 #include "../command_func.h"
00015 #include "../network/network.h"
00016 #include "../string_func.h"
00017 #include "../textbuf_gui.h"
00018 #include "../settings_type.h"
00019 #include "../network/network_content.h"
00020 
00021 #include "ai.hpp"
00022 #include "api/ai_log.hpp"
00023 #include "ai_config.hpp"
00024 
00025 #include "table/strings.h"
00026 
00030 struct AIListWindow : public Window {
00032   enum AIListWindowWidgets {
00033     AIL_WIDGET_CLOSEBOX = 0,     
00034     AIL_WIDGET_CAPTION,          
00035     AIL_WIDGET_LIST,             
00036     AIL_WIDGET_SCROLLBAR,        
00037     AIL_WIDGET_INFO_BG,          
00038     AIL_WIDGET_ACCEPT,           
00039     AIL_WIDGET_CANCEL,           
00040     AIL_WIDGET_CONTENT_DOWNLOAD, 
00041     AIL_WIDGET_RESIZE,           
00042   };
00043 
00044   const AIInfoList *ai_info_list;
00045   int selected;
00046   CompanyID slot;
00047 
00048   AIListWindow(const WindowDesc *desc, CompanyID slot) : Window(desc, 0),
00049     slot(slot)
00050   {
00051     this->ai_info_list = AI::GetUniqueInfoList();
00052     this->resize.step_height = 14;
00053     this->vscroll.cap = (this->widget[AIL_WIDGET_LIST].bottom - this->widget[AIL_WIDGET_LIST].top) / 14 + 1;
00054     this->widget[AIL_WIDGET_LIST].data = (this->vscroll.cap << 8) + 1;
00055     SetVScrollCount(this, (int)this->ai_info_list->size() + 1);
00056 
00057     /* Try if we can find the currently selected AI */
00058     this->selected = -1;
00059     if (AIConfig::GetConfig(slot)->HasAI()) {
00060       AIInfo *info = AIConfig::GetConfig(slot)->GetInfo();
00061       int i = 0;
00062       for (AIInfoList::const_iterator it = this->ai_info_list->begin(); it != this->ai_info_list->end(); it++, i++) {
00063         if ((*it).second == info) {
00064           this->selected = i;
00065           break;
00066         }
00067       }
00068     }
00069 
00070     this->FindWindowPlacementAndResize(desc);
00071   }
00072 
00073   virtual void OnPaint()
00074   {
00075     this->DrawWidgets();
00076 
00077     /* Draw a list of all available AIs. */
00078     int y = this->widget[AIL_WIDGET_LIST].top;
00079     /* First AI in the list is hardcoded to random */
00080     if (this->vscroll.pos == 0) {
00081       DrawStringTruncated(4, y + 3, STR_AI_RANDOM_AI, this->selected == -1 ? TC_WHITE : TC_BLACK, this->width - 8);
00082       y += 14;
00083     }
00084     AIInfo *selected_info = NULL;
00085     AIInfoList::const_iterator it = this->ai_info_list->begin();
00086     for (int i = 1; it != this->ai_info_list->end(); i++, it++) {
00087       if (this->selected == i - 1) selected_info = (*it).second;
00088       if (IsInsideBS(i, this->vscroll.pos, this->vscroll.cap)) {
00089         DoDrawStringTruncated((*it).second->GetName(), 4, y + 3, (this->selected == i - 1) ? TC_WHITE : TC_BLACK, this->width - 8);
00090         y += 14;
00091       }
00092     }
00093 
00094     /* Some info about the currently selected AI. */
00095     if (selected_info != NULL) {
00096       int y = this->widget[AIL_WIDGET_INFO_BG].top + 6;
00097       int x = DrawString(4, y, STR_AI_AUTHOR, TC_BLACK);
00098       DoDrawStringTruncated(selected_info->GetAuthor(), x + 5, y, TC_BLACK, this->width - x - 8);
00099       y += 13;
00100       x = DrawString(4, y, STR_AI_VERSION, TC_BLACK);
00101       static char buf[8];
00102       sprintf(buf, "%d", selected_info->GetVersion());
00103       DoDrawStringTruncated(buf, x + 5, y, TC_BLACK, this->width - x - 8);
00104       y += 13;
00105       SetDParamStr(0, selected_info->GetDescription());
00106       DrawStringMultiLine(4, y, STR_JUST_RAW_STRING, this->width - 8, this->widget[AIL_WIDGET_INFO_BG].bottom - y);
00107     }
00108   }
00109 
00110   void ChangeAI()
00111   {
00112     if (this->selected == -1) {
00113       AIConfig::GetConfig(slot)->ChangeAI(NULL);
00114     } else {
00115       AIInfoList::const_iterator it = this->ai_info_list->begin();
00116       for (int i = 0; i < this->selected; i++) it++;
00117       AIConfig::GetConfig(slot)->ChangeAI((*it).second->GetInstanceName(), (*it).second->GetVersion());
00118     }
00119     InvalidateWindow(WC_GAME_OPTIONS, 0);
00120   }
00121 
00122   virtual void OnClick(Point pt, int widget)
00123   {
00124     switch (widget) {
00125       case AIL_WIDGET_LIST: { // Select one of the AIs
00126         int sel = (pt.y - this->widget[AIL_WIDGET_LIST].top) / 14 + this->vscroll.pos - 1;
00127         if (sel < (int)this->ai_info_list->size()) {
00128           this->selected = sel;
00129           this->SetDirty();
00130         }
00131         break;
00132       }
00133 
00134       case AIL_WIDGET_ACCEPT: {
00135         this->ChangeAI();
00136         delete this;
00137         break;
00138       }
00139 
00140       case AIL_WIDGET_CANCEL:
00141         delete this;
00142         break;
00143 
00144       case AIL_WIDGET_CONTENT_DOWNLOAD:
00145         if (!_network_available) {
00146           ShowErrorMessage(INVALID_STRING_ID, STR_NETWORK_ERR_NOTAVAILABLE, 0, 0);
00147         } else {
00148 #if defined(ENABLE_NETWORK)
00149           ShowNetworkContentListWindow(NULL, CONTENT_TYPE_AI);
00150 #endif
00151         }
00152         break;
00153     }
00154   }
00155 
00156   virtual void OnDoubleClick(Point pt, int widget)
00157   {
00158     switch (widget) {
00159       case AIL_WIDGET_LIST: {
00160         int sel = (pt.y - this->widget[AIL_WIDGET_LIST].top) / 14 + this->vscroll.pos - 1;
00161         if (sel < (int)this->ai_info_list->size()) {
00162           this->selected = sel;
00163           this->ChangeAI();
00164           delete this;
00165         }
00166         break;
00167       }
00168     }
00169   }
00170 
00171   virtual void OnResize(Point new_size, Point delta)
00172   {
00173     if (delta.x != 0) {
00174       ResizeButtons(this, AIL_WIDGET_ACCEPT, AIL_WIDGET_CANCEL);
00175     }
00176 
00177     this->vscroll.cap += delta.y / 14;
00178     this->widget[AIL_WIDGET_LIST].data = (this->vscroll.cap << 8) + 1;
00179   }
00180 };
00181 
00182 /* Widget definition for the ai list window. */
00183 static const Widget _ai_list_widgets[] = {
00184 {   WWT_CLOSEBOX,   RESIZE_NONE,  COLOUR_MAUVE,    0,   10,    0,   13,  STR_00C5,                 STR_018B_CLOSE_WINDOW},             // AIL_WIDGET_CLOSEBOX
00185 {    WWT_CAPTION,  RESIZE_RIGHT,  COLOUR_MAUVE,   11,  199,    0,   13,  STR_AI_LIST_CAPTION,      STR_018C_WINDOW_TITLE_DRAG_THIS},   // AIL_WIDGET_CAPTION
00186 {     WWT_MATRIX,     RESIZE_RB,  COLOUR_MAUVE,    0,  187,   14,  125,  0x501,                    STR_AI_AILIST_TIP},                 // AIL_WIDGET_LIST
00187 {  WWT_SCROLLBAR,    RESIZE_LRB,  COLOUR_MAUVE,  188,  199,   14,  125,  0x0,                      STR_0190_SCROLL_BAR_SCROLLS_LIST }, // AIL_WIDGET_SCROLLBAR
00188 {      WWT_PANEL,    RESIZE_RTB,  COLOUR_MAUVE,    0,  199,  126,  209,  0x0,                      STR_NULL},                          // AIL_WIDGET_INFO_BG
00189 { WWT_PUSHTXTBTN,     RESIZE_TB,  COLOUR_MAUVE,    0,   99,  210,  221,  STR_AI_ACCEPT,            STR_AI_ACCEPT_TIP},                 // AIL_WIDGET_ACCEPT
00190 { WWT_PUSHTXTBTN,    RESIZE_RTB,  COLOUR_MAUVE,  100,  199,  210,  221,  STR_AI_CANCEL,            STR_AI_CANCEL_TIP},                 // AIL_WIDGET_CANCEL
00191 { WWT_PUSHTXTBTN,    RESIZE_RTB,  COLOUR_MAUVE,    0,  187,  222,  233,  STR_CONTENT_INTRO_BUTTON, STR_CONTENT_INTRO_BUTTON_TIP},      // AIL_WIDGET_DOWNLOAD_CONTENT
00192 {  WWT_RESIZEBOX,   RESIZE_LRTB,  COLOUR_MAUVE,  188,  199,  222,  233,  STR_NULL,                 STR_RESIZE_BUTTON},                 // AIL_WIDGET_RESIZE
00193 {   WIDGETS_END},
00194 };
00195 
00196 /* Window definition for the ai list window. */
00197 static const WindowDesc _ai_list_desc = {
00198   WDP_CENTER, WDP_CENTER, 200, 234, 200, 234,
00199   WC_AI_LIST, WC_NONE,
00200   WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_RESIZABLE,
00201   _ai_list_widgets
00202 };
00203 
00204 void ShowAIListWindow(CompanyID slot)
00205 {
00206   DeleteWindowByClass(WC_AI_LIST);
00207   new AIListWindow(&_ai_list_desc, slot);
00208 }
00209 
00213 struct AISettingsWindow : public Window {
00215   enum AISettingsWindowWidgest {
00216     AIS_WIDGET_CLOSEBOX = 0, 
00217     AIS_WIDGET_CAPTION,      
00218     AIS_WIDGET_BACKGROUND,   
00219     AIS_WIDGET_SCROLLBAR,    
00220     AIS_WIDGET_ACCEPT,       
00221     AIS_WIDGET_RESET,        
00222     AIS_WIDGET_RESIZE,       
00223   };
00224 
00225   CompanyID slot;
00226   AIConfig *ai_config;
00227   int clicked_button;
00228   bool clicked_increase;
00229   int timeout;
00230   int clicked_row;
00231 
00232   AISettingsWindow(const WindowDesc *desc, CompanyID slot) : Window(desc, 0),
00233     slot(slot),
00234     clicked_button(-1),
00235     timeout(0)
00236   {
00237     this->FindWindowPlacementAndResize(desc);
00238     this->ai_config = AIConfig::GetConfig(slot);
00239     this->resize.step_height = 14;
00240     this->vscroll.cap = (this->widget[AIS_WIDGET_BACKGROUND].bottom - this->widget[AIS_WIDGET_BACKGROUND].top) / 14 + 1;
00241     this->widget[AIS_WIDGET_BACKGROUND].data = (this->vscroll.cap << 8) + 1;
00242     SetVScrollCount(this, (int)this->ai_config->GetConfigList()->size());
00243     this->FindWindowPlacementAndResize(desc);
00244   }
00245 
00246   virtual void OnPaint()
00247   {
00248     this->DrawWidgets();
00249 
00250     AIConfig *config = this->ai_config;
00251     AIConfigItemList::const_iterator it = config->GetConfigList()->begin();
00252     int i = 0;
00253     for (; i < this->vscroll.pos; i++) it++;
00254 
00255     int y = this->widget[AIS_WIDGET_BACKGROUND].top;
00256     for (; i < this->vscroll.pos + this->vscroll.cap && it != config->GetConfigList()->end(); i++, it++) {
00257       int current_value = config->GetSetting((*it).name);
00258 
00259       int x = 0;
00260       if (((*it).flags & AICONFIG_BOOLEAN) != 0) {
00261         DrawFrameRect(4, y  + 2, 23, y + 10, (current_value != 0) ? COLOUR_GREEN : COLOUR_RED, (current_value != 0) ? FR_LOWERED : FR_NONE);
00262       } else {
00263         DrawArrowButtons(4, y + 2, COLOUR_YELLOW, (this->clicked_button == i) ? 1 + !!this->clicked_increase : 0, current_value > (*it).min_value, current_value < (*it).max_value);
00264         if (it->labels != NULL && it->labels->Find(current_value) != it->labels->End()) {
00265           x = DoDrawStringTruncated(it->labels->Find(current_value)->second, 28, y + 3, TC_ORANGE, this->width - 32);
00266         } else {
00267           SetDParam(0, current_value);
00268           x = DrawStringTruncated(28, y + 3, STR_JUST_INT, TC_ORANGE, this->width - 32);
00269         }
00270       }
00271 
00272       DoDrawStringTruncated((*it).description, max(x + 3, 54), y + 3, TC_LIGHT_BLUE, this->width - (4 + max(x + 3, 54)));
00273       y += 14;
00274     }
00275   }
00276 
00277   virtual void OnClick(Point pt, int widget)
00278   {
00279     switch (widget) {
00280       case AIS_WIDGET_BACKGROUND: {
00281         int num = (pt.y - this->widget[AIS_WIDGET_BACKGROUND].top) / 14 + this->vscroll.pos;
00282         if (num >= (int)this->ai_config->GetConfigList()->size()) break;
00283 
00284         AIConfigItemList::const_iterator it = this->ai_config->GetConfigList()->begin();
00285         for (int i = 0; i < num; i++) it++;
00286         AIConfigItem config_item = *it;
00287         bool bool_item = (config_item.flags & AICONFIG_BOOLEAN) != 0;
00288 
00289         const int x = pt.x - 4;
00290         /* One of the arrows is clicked (or green/red rect in case of bool value) */
00291         if (IsInsideMM(x, 0, 21)) {
00292           int new_val = this->ai_config->GetSetting(config_item.name);
00293           if (bool_item) {
00294             new_val = !new_val;
00295           } else if (x >= 10) {
00296             /* Increase button clicked */
00297             new_val += config_item.step_size;
00298             if (new_val > config_item.max_value) new_val = config_item.max_value;
00299             this->clicked_increase = true;
00300           } else {
00301             /* Decrease button clicked */
00302             new_val -= config_item.step_size;
00303             if (new_val < config_item.min_value) new_val = config_item.min_value;
00304             this->clicked_increase = false;
00305           }
00306 
00307           this->ai_config->SetSetting(config_item.name, new_val);
00308           this->clicked_button = num;
00309           this->timeout = 5;
00310 
00311           if (_settings_newgame.difficulty.diff_level != 3) {
00312             _settings_newgame.difficulty.diff_level = 3;
00313             ShowErrorMessage(INVALID_STRING_ID, STR_DIFFICULTY_TO_CUSTOM, 0, 0);
00314           }
00315         } else if (!bool_item) {
00316           /* Display a query box so users can enter a custom value. */
00317           this->clicked_row = num;
00318           SetDParam(0, this->ai_config->GetSetting(config_item.name));
00319           ShowQueryString(STR_CONFIG_SETTING_INT32, STR_CONFIG_SETTING_QUERY_CAPT, 10, 100, this, CS_NUMERAL, QSF_NONE);
00320         }
00321 
00322         this->SetDirty();
00323         break;
00324       }
00325 
00326       case AIS_WIDGET_ACCEPT:
00327         delete this;
00328         break;
00329 
00330       case AIS_WIDGET_RESET:
00331         this->ai_config->ResetSettings();
00332         this->SetDirty();
00333         break;
00334     }
00335   }
00336 
00337   virtual void OnQueryTextFinished(char *str)
00338   {
00339     if (StrEmpty(str)) return;
00340     AIConfigItemList::const_iterator it = this->ai_config->GetConfigList()->begin();
00341     for (int i = 0; i < this->clicked_row; i++) it++;
00342     int32 value = atoi(str);
00343     this->ai_config->SetSetting((*it).name, value);
00344     this->SetDirty();
00345   }
00346 
00347   virtual void OnResize(Point new_size, Point delta)
00348   {
00349     if (delta.x != 0) {
00350       ResizeButtons(this, AIS_WIDGET_ACCEPT, AIS_WIDGET_RESET);
00351     }
00352 
00353     this->vscroll.cap += delta.y / 14;
00354     this->widget[AIS_WIDGET_BACKGROUND].data = (this->vscroll.cap << 8) + 1;
00355   }
00356 
00357   virtual void OnTick()
00358   {
00359     if (--this->timeout == 0) {
00360       this->clicked_button = -1;
00361       this->SetDirty();
00362     }
00363   }
00364 };
00365 
00366 /* Widget definition for the AI settings window. */
00367 static const Widget _ai_settings_widgets[] = {
00368 {   WWT_CLOSEBOX,   RESIZE_NONE,  COLOUR_MAUVE,    0,   10,    0,   13,  STR_00C5,                 STR_018B_CLOSE_WINDOW},             // AIS_WIDGET_CLOSEBOX
00369 {    WWT_CAPTION,  RESIZE_RIGHT,  COLOUR_MAUVE,   11,  199,    0,   13,  STR_AI_SETTINGS_CAPTION,  STR_018C_WINDOW_TITLE_DRAG_THIS},   // AIS_WIDGET_CAPTION
00370 {     WWT_MATRIX,     RESIZE_RB,  COLOUR_MAUVE,    0,  187,   14,  195,  0x501,                    STR_NULL},                          // AIS_WIDGET_BACKGROUND
00371 {  WWT_SCROLLBAR,    RESIZE_LRB,  COLOUR_MAUVE,  188,  199,   14,  195,  0x0,                      STR_0190_SCROLL_BAR_SCROLLS_LIST }, // AIS_WIDGET_SCROLLBAR
00372 { WWT_PUSHTXTBTN,     RESIZE_TB,  COLOUR_MAUVE,    0,   93,  196,  207,  STR_AI_CLOSE,             STR_NULL},                          // AIS_WIDGET_ACCEPT
00373 { WWT_PUSHTXTBTN,    RESIZE_RTB,  COLOUR_MAUVE,   94,  187,  196,  207,  STR_AI_RESET,             STR_NULL},                          // AIS_WIDGET_RESET
00374 {  WWT_RESIZEBOX,   RESIZE_LRTB,  COLOUR_MAUVE,  188,  199,  196,  207,  STR_NULL,                 STR_RESIZE_BUTTON},                 // AIS_WIDGET_RESIZE
00375 {   WIDGETS_END},
00376 };
00377 
00378 /* Window definition for the AI settings window. */
00379 static const WindowDesc _ai_settings_desc = {
00380   WDP_CENTER, WDP_CENTER, 200, 208, 500, 208,
00381   WC_AI_SETTINGS, WC_NONE,
00382   WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_RESIZABLE,
00383   _ai_settings_widgets
00384 };
00385 
00386 void ShowAISettingsWindow(CompanyID slot)
00387 {
00388   DeleteWindowByClass(WC_AI_LIST);
00389   DeleteWindowByClass(WC_AI_SETTINGS);
00390   new AISettingsWindow(&_ai_settings_desc, slot);
00391 }
00392 
00393 /* Widget definition for the configure AI window. */
00394 static const Widget _ai_config_widgets[] = {
00395 {   WWT_CLOSEBOX,   RESIZE_NONE,  COLOUR_MAUVE,    0,   10,    0,   13,  STR_00C5,               STR_018B_CLOSE_WINDOW},            // AIC_WIDGET_CLOSEBOX
00396 {    WWT_CAPTION,  RESIZE_RIGHT,  COLOUR_MAUVE,   11,  299,    0,   13,  STR_AI_CONFIG_CAPTION,  STR_018C_WINDOW_TITLE_DRAG_THIS},  // AIC_WIDGET_CAPTION
00397 {      WWT_PANEL,     RESIZE_RB,  COLOUR_MAUVE,    0,  299,   14,  171,  0x0,                    STR_NULL},                         // AIC_WIDGET_BACKGROUND
00398 {     WWT_MATRIX,     RESIZE_RB,  COLOUR_MAUVE,    0,  287,   30,  141,  0x501,                  STR_AI_LIST_TIP},                  // AIC_WIDGET_LIST
00399 {  WWT_SCROLLBAR,     RESIZE_LRB, COLOUR_MAUVE,  288,  299,   30,  141,  STR_NULL,               STR_0190_SCROLL_BAR_SCROLLS_LIST}, // AIC_WIDGET_SCROLLBAR
00400 { WWT_PUSHTXTBTN,     RESIZE_TB,  COLOUR_YELLOW,  10,  102,  151,  162,  STR_AI_CHANGE,          STR_AI_CHANGE_TIP},                // AIC_WIDGET_CHANGE
00401 { WWT_PUSHTXTBTN,     RESIZE_TB,  COLOUR_YELLOW, 103,  195,  151,  162,  STR_AI_CONFIGURE,       STR_AI_CONFIGURE_TIP},             // AIC_WIDGET_CONFIGURE
00402 { WWT_PUSHTXTBTN,     RESIZE_TB,  COLOUR_YELLOW, 196,  289,  151,  162,  STR_AI_CLOSE,           STR_NULL},                         // AIC_WIDGET_CLOSE
00403 {   WIDGETS_END},
00404 };
00405 
00406 /* Window definition for the configure AI window. */
00407 static const WindowDesc _ai_config_desc = {
00408   WDP_CENTER, WDP_CENTER, 300, 172, 300, 172,
00409   WC_GAME_OPTIONS, WC_NONE,
00410   WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
00411   _ai_config_widgets
00412 };
00413 
00417 struct AIConfigWindow : public Window {
00419   enum AIConfigWindowWidgets {
00420     AIC_WIDGET_CLOSEBOX = 0, 
00421     AIC_WIDGET_CAPTION,      
00422     AIC_WIDGET_BACKGROUND,   
00423     AIC_WIDGET_LIST,         
00424     AIC_WIDGET_SCROLLBAR,    
00425     AIC_WIDGET_CHANGE,       
00426     AIC_WIDGET_CONFIGURE,    
00427     AIC_WIDGET_CLOSE,        
00428     AIC_WIDGET_RESIZE,       
00429   };
00430 
00431   CompanyID selected_slot;
00432   bool clicked_button;
00433   bool clicked_increase;
00434   int timeout;
00435 
00436   AIConfigWindow() : Window(&_ai_config_desc),
00437     clicked_button(false),
00438     timeout(0)
00439   {
00440     selected_slot = INVALID_COMPANY;
00441     this->resize.step_height = 14;
00442     this->vscroll.cap = (this->widget[AIC_WIDGET_LIST].bottom - this->widget[AIC_WIDGET_LIST].top) / 14 + 1;
00443     this->widget[AIC_WIDGET_LIST].data = (this->vscroll.cap << 8) + 1;
00444     SetVScrollCount(this, MAX_COMPANIES);
00445     this->FindWindowPlacementAndResize(&_ai_config_desc);
00446   }
00447 
00448   ~AIConfigWindow()
00449   {
00450     DeleteWindowByClass(WC_AI_LIST);
00451     DeleteWindowByClass(WC_AI_SETTINGS);
00452   }
00453 
00454   virtual void OnPaint()
00455   {
00456     this->SetWidgetDisabledState(AIC_WIDGET_CHANGE, selected_slot == INVALID_COMPANY);
00457     this->SetWidgetDisabledState(AIC_WIDGET_CONFIGURE, selected_slot == INVALID_COMPANY);
00458     this->DrawWidgets();
00459 
00460     byte max_competitors = _settings_newgame.difficulty.max_no_competitors;
00461     DrawArrowButtons(10, 18, COLOUR_YELLOW, this->clicked_button ? 1 + !!this->clicked_increase : 0, max_competitors > 0, max_competitors < MAX_COMPANIES - 1);
00462     SetDParam(0, _settings_newgame.difficulty.max_no_competitors);
00463     DrawString(36, 18, STR_6805_MAXIMUM_NO_COMPETITORS, TC_FROMSTRING);
00464 
00465     int y = this->widget[AIC_WIDGET_LIST].top;
00466     for (int i = this->vscroll.pos; i < this->vscroll.pos + this->vscroll.cap && i < MAX_COMPANIES; i++) {
00467       StringID text;
00468 
00469       if (AIConfig::GetConfig((CompanyID)i)->GetInfo() != NULL) {
00470         SetDParamStr(0, AIConfig::GetConfig((CompanyID)i)->GetInfo()->GetName());
00471         text = STR_JUST_RAW_STRING;
00472       } else if (i == 0) {
00473         text = STR_AI_HUMAN_PLAYER;
00474       } else {
00475         text = STR_AI_RANDOM_AI;
00476       }
00477       DrawStringTruncated(10, y + 3, text, (this->selected_slot == i) ? TC_WHITE : ((i > _settings_newgame.difficulty.max_no_competitors || i == 0) ? TC_SILVER : TC_ORANGE), this->width - 20);
00478       y += 14;
00479     }
00480   }
00481 
00482   virtual void OnClick(Point pt, int widget)
00483   {
00484     switch (widget) {
00485       case AIC_WIDGET_BACKGROUND: {
00486         /* Check if the user clicked on one of the arrows to configure the number of AIs */
00487         if (IsInsideBS(pt.x, 10, 20) && IsInsideBS(pt.y, 18, 10)) {
00488           if (pt.x <= 20) {
00489             _settings_newgame.difficulty.max_no_competitors = max(0, _settings_newgame.difficulty.max_no_competitors - 1);
00490           } else {
00491             _settings_newgame.difficulty.max_no_competitors = min(MAX_COMPANIES - 1, _settings_newgame.difficulty.max_no_competitors + 1);
00492           }
00493           if (_settings_newgame.difficulty.diff_level != 3) {
00494             _settings_newgame.difficulty.diff_level = 3;
00495             ShowErrorMessage(INVALID_STRING_ID, STR_DIFFICULTY_TO_CUSTOM, 0, 0);
00496           }
00497           this->SetDirty();
00498         }
00499         break;
00500       }
00501 
00502       case AIC_WIDGET_LIST: { // Select a slot
00503         uint slot = (pt.y - this->widget[AIC_WIDGET_LIST].top) / 14 + this->vscroll.pos;
00504 
00505         if (slot == 0 || slot > _settings_newgame.difficulty.max_no_competitors) slot = INVALID_COMPANY;
00506         this->selected_slot = (CompanyID)slot;
00507         this->SetDirty();
00508         break;
00509       }
00510 
00511       case AIC_WIDGET_CHANGE:  // choose other AI
00512         ShowAIListWindow((CompanyID)this->selected_slot);
00513         break;
00514 
00515       case AIC_WIDGET_CONFIGURE: // change the settings for an AI
00516         ShowAISettingsWindow((CompanyID)this->selected_slot);
00517         break;
00518 
00519       case AIC_WIDGET_CLOSE:
00520         delete this;
00521         break;
00522     }
00523   }
00524 
00525   virtual void OnDoubleClick(Point pt, int widget)
00526   {
00527     switch (widget) {
00528       case AIC_WIDGET_LIST:
00529         this->OnClick(pt, widget);
00530         if (this->selected_slot != INVALID_COMPANY) ShowAIListWindow((CompanyID)this->selected_slot);
00531         break;
00532     }
00533   }
00534 
00535   virtual void OnResize(Point new_size, Point delta)
00536   {
00537     this->vscroll.cap += delta.y / 14;
00538     this->widget[AIC_WIDGET_LIST].data = (this->vscroll.cap << 8) + 1;
00539   }
00540 
00541   virtual void OnTick()
00542   {
00543     if (--this->timeout == 0) {
00544       this->clicked_button = false;
00545       this->SetDirty();
00546     }
00547   }
00548 };
00549 
00550 void ShowAIConfigWindow()
00551 {
00552   DeleteWindowById(WC_GAME_OPTIONS, 0);
00553   new AIConfigWindow();
00554 }
00555 
00556 struct AIDebugWindow : public Window {
00557   enum AIDebugWindowWidgets {
00558     AID_WIDGET_CLOSEBOX = 0,
00559     AID_WIDGET_CAPTION,
00560     AID_WIDGET_VIEW,
00561     AID_WIDGET_NAME_TEXT,
00562     AID_WIDGET_RELOAD_TOGGLE,
00563     AID_WIDGET_LOG_PANEL,
00564     AID_WIDGET_SCROLLBAR,
00565     AID_WIDGET_UNUSED_1,
00566     AID_WIDGET_UNUSED_2,
00567     AID_WIDGET_UNUSED_3,
00568     AID_WIDGET_UNUSED_4,
00569     AID_WIDGET_UNUSED_5,
00570     AID_WIDGET_UNUSED_6,
00571     AID_WIDGET_UNUSED_7,
00572 
00573     AID_WIDGET_COMPANY_BUTTON_START,
00574     AID_WIDGET_COMPANY_BUTTON_END = AID_WIDGET_COMPANY_BUTTON_START + 14,
00575   };
00576 
00577   static CompanyID ai_debug_company;
00578   int redraw_timer;
00579 
00580   AIDebugWindow(const WindowDesc *desc, WindowNumber number) : Window(desc, number)
00581   {
00582     /* Disable the companies who are not active or not an AI */
00583     for (CompanyID i = COMPANY_FIRST; i < MAX_COMPANIES; i++) {
00584       this->SetWidgetDisabledState(i + AID_WIDGET_COMPANY_BUTTON_START, !IsValidCompanyID(i) || !GetCompany(i)->is_ai);
00585     }
00586     this->DisableWidget(AID_WIDGET_RELOAD_TOGGLE);
00587 
00588     this->vscroll.cap = 14;
00589     this->vscroll.pos = 0;
00590     this->resize.step_height = 12;
00591 
00592     if (ai_debug_company != INVALID_COMPANY) this->LowerWidget(ai_debug_company + AID_WIDGET_COMPANY_BUTTON_START);
00593 
00594     this->FindWindowPlacementAndResize(desc);
00595   }
00596 
00597   virtual void OnPaint()
00598   {
00599     /* Check if the currently selected company is still active. */
00600     if (ai_debug_company == INVALID_COMPANY || !IsValidCompanyID(ai_debug_company)) {
00601       if (ai_debug_company != INVALID_COMPANY) {
00602         /* Raise and disable the widget for the previous selection. */
00603         this->RaiseWidget(ai_debug_company + AID_WIDGET_COMPANY_BUTTON_START);
00604         this->DisableWidget(ai_debug_company + AID_WIDGET_COMPANY_BUTTON_START);
00605 
00606         ai_debug_company = INVALID_COMPANY;
00607       }
00608 
00609       for (CompanyID i = COMPANY_FIRST; i < MAX_COMPANIES; i++) {
00610         if (IsValidCompanyID(i) && GetCompany(i)->is_ai) {
00611           /* Lower the widget corresponding to this company. */
00612           this->LowerWidget(i + AID_WIDGET_COMPANY_BUTTON_START);
00613 
00614           ai_debug_company = i;
00615           break;
00616         }
00617       }
00618     }
00619 
00620     /* Update "Reload AI" button */
00621     this->SetWidgetDisabledState(AID_WIDGET_RELOAD_TOGGLE, ai_debug_company == INVALID_COMPANY);
00622 
00623     /* Draw standard stuff */
00624     this->DrawWidgets();
00625 
00626     /* If there are no active companies, don't display anything else. */
00627     if (ai_debug_company == INVALID_COMPANY) return;
00628 
00629     /* Paint the company icons */
00630     for (CompanyID i = COMPANY_FIRST; i < MAX_COMPANIES; i++) {
00631       if (!IsValidCompanyID(i) || !GetCompany(i)->is_ai) {
00632         /* Check if we have the company as an active company */
00633         if (!this->IsWidgetDisabled(i + AID_WIDGET_COMPANY_BUTTON_START)) {
00634           /* Bah, company gone :( */
00635           this->DisableWidget(i + AID_WIDGET_COMPANY_BUTTON_START);
00636 
00637           /* We need a repaint */
00638           this->SetDirty();
00639         }
00640         continue;
00641       }
00642 
00643       /* Check if we have the company marked as inactive */
00644       if (this->IsWidgetDisabled(i + AID_WIDGET_COMPANY_BUTTON_START)) {
00645         /* New AI! Yippie :p */
00646         this->EnableWidget(i + AID_WIDGET_COMPANY_BUTTON_START);
00647 
00648         /* We need a repaint */
00649         this->SetDirty();
00650       }
00651 
00652       byte x = (i == ai_debug_company) ? 1 : 0;
00653       DrawCompanyIcon(i, (i % 8) * 37 + 13 + x, (i < 8 ? 0 : 13) + 16 + x);
00654     }
00655 
00656     /* Draw the AI name */
00657     AIInfo *info = GetCompany(ai_debug_company)->ai_info;
00658     assert(info != NULL);
00659     char name[1024];
00660     snprintf(name, sizeof(name), "%s (v%d)", info->GetName(), info->GetVersion());
00661     DoDrawString(name, 7, 47, TC_BLACK);
00662 
00663     CompanyID old_company = _current_company;
00664     _current_company = ai_debug_company;
00665     AILog::LogData *log = (AILog::LogData *)AIObject::GetLogPointer();
00666     _current_company = old_company;
00667 
00668     SetVScrollCount(this, (log == NULL) ? 0 : log->used);
00669     this->InvalidateWidget(AID_WIDGET_SCROLLBAR);
00670     if (log == NULL) return;
00671 
00672     int y = 6;
00673     for (int i = this->vscroll.pos; i < (this->vscroll.cap + this->vscroll.pos); i++) {
00674       uint pos = (log->count + log->pos - i) % log->count;
00675       if (log->lines[pos] == NULL) break;
00676 
00677       TextColour colour;
00678       switch (log->type[pos]) {
00679         case AILog::LOG_SQ_INFO:  colour = TC_BLACK;  break;
00680         case AILog::LOG_SQ_ERROR: colour = TC_RED;    break;
00681         case AILog::LOG_INFO:     colour = TC_BLACK;  break;
00682         case AILog::LOG_WARNING:  colour = TC_YELLOW; break;
00683         case AILog::LOG_ERROR:    colour = TC_RED;    break;
00684         default:                  colour = TC_BLACK;  break;
00685       }
00686 
00687       DoDrawStringTruncated(log->lines[pos], 7, this->widget[AID_WIDGET_LOG_PANEL].top + y, colour, this->widget[AID_WIDGET_LOG_PANEL].right - this->widget[AID_WIDGET_LOG_PANEL].left - 14);
00688       y += 12;
00689     }
00690   }
00691 
00692   virtual void OnClick(Point pt, int widget)
00693   {
00694     /* Check which button is clicked */
00695     if (IsInsideMM(widget, AID_WIDGET_COMPANY_BUTTON_START, AID_WIDGET_COMPANY_BUTTON_END + 1)) {
00696       /* Is it no on disable? */
00697       if (!this->IsWidgetDisabled(widget)) {
00698         this->RaiseWidget(ai_debug_company + AID_WIDGET_COMPANY_BUTTON_START);
00699         ai_debug_company = (CompanyID)(widget - AID_WIDGET_COMPANY_BUTTON_START);
00700         this->LowerWidget(ai_debug_company + AID_WIDGET_COMPANY_BUTTON_START);
00701         this->SetDirty();
00702       }
00703     }
00704     if (widget == AID_WIDGET_RELOAD_TOGGLE && !this->IsWidgetDisabled(widget)) {
00705       /* First kill the company of the AI, then start a new one. This should start the current AI again */
00706       DoCommandP(0, 2, ai_debug_company, CMD_COMPANY_CTRL);
00707       DoCommandP(0, 1, 0, CMD_COMPANY_CTRL);
00708     }
00709   }
00710 
00711   virtual void OnTimeout()
00712   {
00713     this->RaiseWidget(AID_WIDGET_RELOAD_TOGGLE);
00714     this->SetDirty();
00715   }
00716 
00717   virtual void OnInvalidateData(int data = 0)
00718   {
00719     if (data == -1 || ai_debug_company == data) this->SetDirty();
00720   }
00721 
00722   virtual void OnResize(Point new_size, Point delta)
00723   {
00724     this->vscroll.cap += delta.y / (int)this->resize.step_height;
00725   }
00726 };
00727 
00728 CompanyID AIDebugWindow::ai_debug_company = INVALID_COMPANY;
00729 
00730 static const Widget _ai_debug_widgets[] = {
00731 {   WWT_CLOSEBOX,   RESIZE_NONE,  COLOUR_GREY,     0,    10,     0,    13, STR_00C5,                   STR_018B_CLOSE_WINDOW},                 // AID_WIDGET_CLOSEBOX
00732 {    WWT_CAPTION,  RESIZE_RIGHT,  COLOUR_GREY,    11,   298,     0,    13, STR_AI_DEBUG,               STR_018C_WINDOW_TITLE_DRAG_THIS},       // AID_WIDGET_CAPTION
00733 {      WWT_PANEL,  RESIZE_RIGHT,  COLOUR_GREY,     0,   298,    14,    40, 0x0,                        STR_NULL},                              // AID_WIDGET_VIEW
00734 
00735 {      WWT_PANEL,  RESIZE_RIGHT,  COLOUR_GREY,     0,   149,    41,    60, 0x0,                        STR_AI_DEBUG_NAME_TIP},                 // AID_WIDGET_NAME_TEXT
00736 { WWT_PUSHTXTBTN,     RESIZE_LR,  COLOUR_GREY,   150,   298,    41,    60, STR_AI_DEBUG_RELOAD,        STR_AI_DEBUG_RELOAD_TIP},               // AID_WIDGET_RELOAD_TOGGLE
00737 {      WWT_PANEL,     RESIZE_RB,  COLOUR_GREY,     0,   286,    61,   240, 0x0,                        STR_NULL},                              // AID_WIDGET_LOG_PANEL
00738 {  WWT_SCROLLBAR,    RESIZE_LRB,  COLOUR_GREY,   287,   298,    61,   228, STR_NULL,                   STR_0190_SCROLL_BAR_SCROLLS_LIST},      // AID_WIDGET_SCROLLBAR
00739 /* As this is WIP, leave the next few so we can work a bit with the GUI */
00740 {      WWT_EMPTY,   RESIZE_NONE,  COLOUR_GREY,     0,   298,   101,   120, 0x0,                        STR_NULL},                              // AID_WIDGET_UNUSED_1
00741 {      WWT_EMPTY,   RESIZE_NONE,  COLOUR_GREY,     0,   298,   121,   140, 0x0,                        STR_NULL},                              // AID_WIDGET_UNUSED_2
00742 {      WWT_EMPTY,   RESIZE_NONE,  COLOUR_GREY,     0,   298,   141,   160, 0x0,                        STR_NULL},                              // AID_WIDGET_UNUSED_3
00743 {      WWT_EMPTY,   RESIZE_NONE,  COLOUR_GREY,     0,   298,   161,   180, 0x0,                        STR_NULL},                              // AID_WIDGET_UNUSED_4
00744 {      WWT_EMPTY,   RESIZE_NONE,  COLOUR_GREY,     0,   298,   181,   200, 0x0,                        STR_NULL},                              // AID_WIDGET_UNUSED_5
00745 {      WWT_EMPTY,   RESIZE_NONE,  COLOUR_GREY,     0,   298,   201,   220, 0x0,                        STR_NULL},                              // AID_WIDGET_UNUSED_6
00746 {      WWT_EMPTY,   RESIZE_NONE,  COLOUR_GREY,     0,   298,   221,   240, 0x0,                        STR_NULL},                              // AID_WIDGET_UNUSED_7
00747 
00748 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_GREY,     2,    38,    14,    26, 0x0,                        STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY}, // AID_WIDGET_COMPANY_BUTTON_START
00749 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_GREY,    39,    75,    14,    26, 0x0,                        STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY},
00750 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_GREY,    76,   112,    14,    26, 0x0,                        STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY},
00751 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_GREY,   113,   149,    14,    26, 0x0,                        STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY},
00752 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_GREY,   150,   186,    14,    26, 0x0,                        STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY},
00753 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_GREY,   187,   223,    14,    26, 0x0,                        STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY},
00754 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_GREY,   224,   260,    14,    26, 0x0,                        STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY},
00755 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_GREY,   261,   297,    14,    26, 0x0,                        STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY},
00756 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_GREY,     2,    38,    27,    39, 0x0,                        STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY},
00757 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_GREY,    39,    75,    27,    39, 0x0,                        STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY},
00758 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_GREY,    76,   112,    27,    39, 0x0,                        STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY},
00759 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_GREY,   113,   149,    27,    39, 0x0,                        STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY},
00760 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_GREY,   150,   186,    27,    39, 0x0,                        STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY},
00761 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_GREY,   187,   223,    27,    39, 0x0,                        STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY},
00762 {      WWT_PANEL,   RESIZE_NONE,  COLOUR_GREY,   224,   260,    27,    39, 0x0,                        STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY}, // AID_WIDGET_COMPANY_BUTTON_END
00763 {  WWT_RESIZEBOX,   RESIZE_LRTB,  COLOUR_GREY,   287,   298,   229,   240, STR_NULL,                   STR_RESIZE_BUTTON},
00764 {   WIDGETS_END},
00765 };
00766 
00767 static const WindowDesc _ai_debug_desc = {
00768   WDP_AUTO, WDP_AUTO, 299, 241, 299, 241,
00769   WC_AI_DEBUG, WC_NONE,
00770   WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_RESIZABLE,
00771   _ai_debug_widgets
00772 };
00773 
00774 void ShowAIDebugWindow()
00775 {
00776   if (!_networking || _network_server) {
00777     AllocateWindowDescFront<AIDebugWindow>(&_ai_debug_desc, 0);
00778   } else {
00779     ShowErrorMessage(INVALID_STRING_ID, STR_AI_DEBUG_SERVER_ONLY, 0, 0);
00780   }
00781 }

Generated on Mon Feb 16 23:12:04 2009 for openttd by  doxygen 1.5.6