ai_gui.cpp

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

Generated on Sun Sep 13 08:19:13 2009 for OpenTTD by  doxygen 1.5.6