16 | } | 16 | }
|
---|
| | 17 |
|
---|
| | 18 |
|
---|
| | 19 | ////BLA BLA CODE ////
|
---|
| | 20 |
|
---|
| | 21 | /**
|
---|
| | 22 | * Window for settings the parameters of an AI.
|
---|
| | 23 | */
|
---|
| | 24 | struct AISettingsWindow : public Window {
|
---|
| | 25 | CompanyID slot; ///< The currently show company's setting.
|
---|
| | 26 | ScriptConfig *ai_config; ///< The configuration we're modifying.
|
---|
| | 27 | int clicked_button; ///< The button we clicked.
|
---|
| | 28 | bool clicked_increase; ///< Whether we clicked the increase or decrease button.
|
---|
| | 29 | bool clicked_dropdown; ///< Whether the dropdown is open.
|
---|
| | 30 | bool closing_dropdown; ///< True, if the dropdown list is currently closing.
|
---|
| | 31 | GUITimer timeout; ///< Timeout for unclicking the button.
|
---|
| | 32 | int clicked_row; ///< The clicked row of settings.
|
---|
| | 33 | int line_height; ///< Height of a row in the matrix widget.
|
---|
| | 34 | Scrollbar *vscroll; ///< Cache of the vertical scrollbar.
|
---|
| | 35 | VisibleSettingsList visible_settings; ///< List of visible AI settings
|
---|
| | 36 |
|
---|
| | 37 | /**
|
---|
| | 38 | * Constructor for the window.
|
---|
| | 39 | * @param desc The description of the window.
|
---|
| | 40 | * @param slot The company we're changing the settings for.
|
---|
| | 41 | */
|
---|
| | 42 | AISettingsWindow(WindowDesc *desc, CompanyID slot) : Window(desc),
|
---|
| | 43 | slot(slot),
|
---|
| | 44 | clicked_button(-1),
|
---|
| | 45 | clicked_dropdown(false),
|
---|
| | 46 | closing_dropdown(false),
|
---|
| | 47 | timeout(0)
|
---|
| | 48 | {
|
---|
| | 49 | this->ai_config = GetConfig(slot);
|
---|
| | 50 |
|
---|
| | 51 | this->CreateNestedTree();
|
---|
| | 52 | this->vscroll = this->GetScrollbar(WID_AIS_SCROLLBAR);
|
---|
| | 53 | this->FinishInitNested(slot); // Initializes 'this->line_height' as side effect.
|
---|
| | 54 |
|
---|
| | 55 | this->SetWidgetDisabledState(WID_AIS_RESET, _game_mode == GM_EDITOR && !IsConsideredDead(this->slot));
|
---|
| | 56 |
|
---|
| | 57 | this->RebuildVisibleSettings();
|
---|
| | 58 | }
|
---|
| | 59 |
|
---|
| | 60 | virtual void SetStringParameters(int widget) const
|
---|
| | 61 | {
|
---|
| | 62 | switch (widget) {
|
---|
| | 63 | case WID_AIS_CAPTION:
|
---|
| | 64 | SetDParam(0, (this->slot == OWNER_DEITY) ? STR_AI_SETTINGS_CAPTION_GAMESCRIPT : STR_AI_SETTINGS_CAPTION_AI);
|
---|
| | 65 | break;
|
---|
| | 66 | }
|
---|
| | 67 | }
|
---|
| | 68 |
|
---|
| | 69 | /**
|
---|
| | 70 | * Rebuilds the list of visible settings. AI settings with the flag
|
---|
| | 71 | * SCRIPTCONFIG_DEVELOPER set will only be visible if the client setting
|
---|
| | 72 | * gui.ai_developer_tools is enabled.
|
---|
| | 73 | */
|
---|
| | 74 | void RebuildVisibleSettings()
|
---|
| | 75 | {
|
---|
| | 76 | this->ai_config = GetConfig(slot);
|
---|
| | 77 | visible_settings.clear();
|
---|
| | 78 | visible_settings.swap(BuildVisibleSettingsList(slot));
|
---|
| | 79 |
|
---|
| | 80 | this->vscroll->SetCount((int)this->visible_settings.size());
|
---|
| | 81 | }
|
---|
| | 82 |
|
---|
| | 83 | virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
|
---|
| | 84 | {
|
---|
| | 85 | if (widget == WID_AIS_BACKGROUND) {
|
---|
| | 86 | this->line_height = max(SETTING_BUTTON_HEIGHT, FONT_HEIGHT_NORMAL) + WD_MATRIX_TOP + WD_MATRIX_BOTTOM;
|
---|
| | 87 |
|
---|
| | 88 | resize->width = 1;
|
---|
| | 89 | resize->height = this->line_height;
|
---|
| | 90 | size->height = 5 * this->line_height;
|
---|
| | 91 | }
|
---|
| | 92 | }
|
---|
| | 93 |
|
---|
| | 94 | virtual void DrawWidget(const Rect &r, int widget) const
|
---|
| | 95 | {
|
---|
| | 96 | if (widget != WID_AIS_BACKGROUND) return;
|
---|
| | 97 |
|
---|
| | 98 | ScriptConfig *config = this->ai_config;
|
---|
| | 99 | VisibleSettingsList::const_iterator it = this->visible_settings.begin();
|
---|
| | 100 | int i = 0;
|
---|
| | 101 | for (; !this->vscroll->IsVisible(i); i++) it++;
|
---|
| | 102 |
|
---|
| | 103 | bool rtl = _current_text_dir == TD_RTL;
|
---|
| | 104 | uint buttons_left = rtl ? r.right - SETTING_BUTTON_WIDTH - 3 : r.left + 4;
|
---|
| | 105 | uint text_left = r.left + (rtl ? WD_FRAMERECT_LEFT : SETTING_BUTTON_WIDTH + 8);
|
---|
| | 106 | uint text_right = r.right - (rtl ? SETTING_BUTTON_WIDTH + 8 : WD_FRAMERECT_RIGHT);
|
---|
| | 107 |
|
---|
| | 108 |
|
---|
| | 109 | int y = r.top;
|
---|
| | 110 | int button_y_offset = (this->line_height - SETTING_BUTTON_HEIGHT) / 2;
|
---|
| | 111 | int text_y_offset = (this->line_height - FONT_HEIGHT_NORMAL) / 2;
|
---|
| | 112 | for (; this->vscroll->IsVisible(i) && it != visible_settings.end(); i++, it++) {
|
---|
| | 113 | const ScriptConfigItem &config_item = **it;
|
---|
| | 114 | int current_value = config->GetSetting((config_item).name);
|
---|
| | 115 | bool editable = this->IsEditableItem(config_item);
|
---|
| | 116 |
|
---|
| | 117 | StringID str;
|
---|
| | 118 | TextColour colour;
|
---|
| | 119 | uint idx = 0;
|
---|
| | 120 | if (StrEmpty(config_item.description)) {
|
---|
| | 121 | if (!strcmp(config_item.name, "start_date")) {
|
---|
| | 122 | /* Build-in translation */
|
---|
| | 123 | str = STR_AI_SETTINGS_START_DELAY;
|
---|
| | 124 | colour = TC_LIGHT_BLUE;
|
---|
| | 125 | } else {
|
---|
| | 126 | str = STR_JUST_STRING;
|
---|
| | 127 | colour = TC_ORANGE;
|
---|
| | 128 | }
|
---|
| | 129 | } else {
|
---|
| | 130 | str = STR_AI_SETTINGS_SETTING;
|
---|
| | 131 | colour = TC_LIGHT_BLUE;
|
---|
| | 132 | SetDParamStr(idx++, config_item.description);
|
---|
| | 133 | }
|
---|
| | 134 |
|
---|
| | 135 | if ((config_item.flags & SCRIPTCONFIG_BOOLEAN) != 0) {
|
---|
| | 136 | DrawBoolButton(buttons_left, y + button_y_offset, current_value != 0, editable);
|
---|
| | 137 | SetDParam(idx++, current_value == 0 ? STR_CONFIG_SETTING_OFF : STR_CONFIG_SETTING_ON);
|
---|
| | 138 | } else {
|
---|
| | 139 | if (config_item.complete_labels) {
|
---|
| | 140 | DrawDropDownButton(buttons_left, y + button_y_offset, COLOUR_YELLOW, this->clicked_row == i && clicked_dropdown, editable);
|
---|
| | 141 | } else {
|
---|
| | 142 | DrawArrowButtons(buttons_left, y + button_y_offset, COLOUR_YELLOW, (this->clicked_button == i) ? 1 + (this->clicked_increase != rtl) : 0, editable && current_value > config_item.min_value, editable && current_value < config_item.max_value);
|
---|
| | 143 | }
|
---|
| | 144 | if (config_item.labels != NULL && config_item.labels->Contains(current_value)) {
|
---|
| | 145 | SetDParam(idx++, STR_JUST_RAW_STRING);
|
---|
| | 146 | SetDParamStr(idx++, config_item.labels->Find(current_value)->second);
|
---|
| | 147 | } else {
|
---|
| | 148 | SetDParam(idx++, STR_JUST_INT);
|
---|
| | 149 | SetDParam(idx++, current_value);
|
---|
| | 150 | }
|
---|
| | 151 | }
|
---|
| | 152 |
|
---|
| | 153 | DrawString(text_left, text_right, y + text_y_offset, str, colour);
|
---|
| | 154 | y += this->line_height;
|
---|
| | 155 | }
|
---|
| | 156 | }
|
---|
| | 157 |
|
---|
| | 158 | virtual void OnPaint()
|
---|
| | 159 | {
|
---|
| | 160 | if (this->closing_dropdown) {
|
---|
| | 161 | this->closing_dropdown = false;
|
---|
| | 162 | this->clicked_dropdown = false;
|
---|
| | 163 | }
|
---|
| | 164 | this->DrawWidgets();
|
---|
| | 165 | }
|
---|
| | 166 |
|
---|
| | 167 | virtual void OnClick(Point pt, int widget, int click_count)
|
---|
| | 168 | {
|
---|
| | 169 | switch (widget) {
|
---|
| | 170 | case WID_AIS_BACKGROUND: {
|
---|
| | 171 | const NWidgetBase *wid = this->GetWidget<NWidgetBase>(WID_AIS_BACKGROUND);
|
---|
| | 172 | int num = (pt.y - wid->pos_y) / this->line_height + this->vscroll->GetPosition();
|
---|
| | 173 | if (num >= (int)this->visible_settings.size()) break;
|
---|
| | 174 |
|
---|
| | 175 | VisibleSettingsList::const_iterator it = this->visible_settings.begin();
|
---|
| | 176 | for (int i = 0; i < num; i++) it++;
|
---|
| | 177 | const ScriptConfigItem config_item = **it;
|
---|
| | 178 | if (!this->IsEditableItem(config_item)) return;
|
---|
| | 179 |
|
---|
| | 180 | if (this->clicked_row != num) {
|
---|
| | 181 | DeleteChildWindows(WC_QUERY_STRING);
|
---|
| | 182 | HideDropDownMenu(this);
|
---|
| | 183 | this->clicked_row = num;
|
---|
| | 184 | this->clicked_dropdown = false;
|
---|
| | 185 | }
|
---|
| | 186 |
|
---|
| | 187 | bool bool_item = (config_item.flags & SCRIPTCONFIG_BOOLEAN) != 0;
|
---|
| | 188 |
|
---|
| | 189 | int x = pt.x - wid->pos_x;
|
---|
| | 190 | if (_current_text_dir == TD_RTL) x = wid->current_x - 1 - x;
|
---|
| | 191 | x -= 4;
|
---|
| | 192 |
|
---|
| | 193 | /* One of the arrows is clicked (or green/red rect in case of bool value) */
|
---|
| | 194 | int old_val = this->ai_config->GetSetting(config_item.name);
|
---|
| | 195 | if (!bool_item && IsInsideMM(x, 0, SETTING_BUTTON_WIDTH) && config_item.complete_labels) {
|
---|
| | 196 | if (this->clicked_dropdown) {
|
---|
| | 197 | /* unclick the dropdown */
|
---|
| | 198 | HideDropDownMenu(this);
|
---|
| | 199 | this->clicked_dropdown = false;
|
---|
| | 200 | this->closing_dropdown = false;
|
---|
| | 201 | } else {
|
---|
| | 202 | const NWidgetBase *wid = this->GetWidget<NWidgetBase>(WID_AIS_BACKGROUND);
|
---|
| | 203 | int rel_y = (pt.y - (int)wid->pos_y) % this->line_height;
|
---|
| | 204 |
|
---|
| | 205 | Rect wi_rect;
|
---|
| | 206 | wi_rect.left = pt.x - (_current_text_dir == TD_RTL ? SETTING_BUTTON_WIDTH - 1 - x : x);
|
---|
| | 207 | wi_rect.right = wi_rect.left + SETTING_BUTTON_WIDTH - 1;
|
---|
| | 208 | wi_rect.top = pt.y - rel_y + (this->line_height - SETTING_BUTTON_HEIGHT) / 2;
|
---|
| | 209 | wi_rect.bottom = wi_rect.top + SETTING_BUTTON_HEIGHT - 1;
|
---|
| | 210 |
|
---|
| | 211 | /* For dropdowns we also have to check the y position thoroughly, the mouse may not above the just opening dropdown */
|
---|
| | 212 | if (pt.y >= wi_rect.top && pt.y <= wi_rect.bottom) {
|
---|
| | 213 | this->clicked_dropdown = true;
|
---|
| | 214 | this->closing_dropdown = false;
|
---|
| | 215 |
|
---|
| | 216 | DropDownList *list = new DropDownList();
|
---|
| | 217 | for (int i = config_item.min_value; i <= config_item.max_value; i++) {
|
---|
| | 218 | *list->Append() = new DropDownListCharStringItem(config_item.labels->Find(i)->second, i, false);
|
---|
| | 219 | }
|
---|
| | 220 |
|
---|
| | 221 | ShowDropDownListAt(this, list, old_val, -1, wi_rect, COLOUR_ORANGE, true);
|
---|
| | 222 | }
|
---|
| | 223 | }
|
---|
| | 224 | } else if (IsInsideMM(x, 0, SETTING_BUTTON_WIDTH)) {
|
---|
| | 225 | int new_val = old_val;
|
---|
| | 226 | if (bool_item) {
|
---|
| | 227 | new_val = !new_val;
|
---|
| | 228 | } else if (x >= SETTING_BUTTON_WIDTH / 2) {
|
---|
| | 229 | /* Increase button clicked */
|
---|
| | 230 | new_val += config_item.step_size;
|
---|
| | 231 | if (new_val > config_item.max_value) new_val = config_item.max_value;
|
---|
| | 232 | this->clicked_increase = true;
|
---|
| | 233 | } else {
|
---|
| | 234 | /* Decrease button clicked */
|
---|
| | 235 | new_val -= config_item.step_size;
|
---|
| | 236 | if (new_val < config_item.min_value) new_val = config_item.min_value;
|
---|
| | 237 | this->clicked_increase = false;
|
---|
| | 238 | }
|
---|
| | 239 |
|
---|
| | 240 | if (new_val != old_val) {
|
---|
| | 241 | this->ai_config->SetSetting(config_item.name, new_val);
|
---|
| | 242 | this->clicked_button = num;
|
---|
| | 243 | this->timeout.SetInterval(150);
|
---|
| | 244 | }
|
---|
| | 245 | } else if (!bool_item && !config_item.complete_labels) {
|
---|
| | 246 | /* Display a query box so users can enter a custom value. */
|
---|
| | 247 | SetDParam(0, old_val);
|
---|
| | 248 | ShowQueryString(STR_JUST_INT, STR_CONFIG_SETTING_QUERY_CAPTION, 10, this, CS_NUMERAL, QSF_NONE);
|
---|
| | 249 | }
|
---|
| | 250 | this->SetDirty();
|
---|
| | 251 | break;
|
---|
| | 252 | }
|
---|
| | 253 |
|
---|
| | 254 | case WID_AIS_ACCEPT:
|
---|
| | 255 | delete this;
|
---|
| | 256 | break;
|
---|
| | 257 |
|
---|
| | 258 | case WID_AIS_RESET:
|
---|
| | 259 | if (_game_mode != GM_EDITOR || IsConsideredDead(this->slot)) {
|
---|
| | 260 | this->ai_config->ResetSettingsGUI(IsConsideredDead(this->slot));
|
---|
| | 261 | this->SetDirty();
|
---|
| | 262 | }
|
---|
| | 263 | break;
|
---|
| | 264 | }
|
---|
| | 265 | }
|
---|
| | 266 |
|
---|
| | 267 | virtual void OnQueryTextFinished(char *str)
|
---|
| | 268 | {
|
---|
| | 269 | if (StrEmpty(str)) return;
|
---|
| | 270 | VisibleSettingsList::const_iterator it = this->visible_settings.begin();
|
---|
| | 271 | for (int i = 0; i < this->clicked_row; i++) it++;
|
---|
| | 272 | const ScriptConfigItem config_item = **it;
|
---|
| | 273 | if (_game_mode != GM_MENU && !IsConsideredDead(this->slot) && (config_item.flags & SCRIPTCONFIG_INGAME) == 0) return;
|
---|
| | 274 | int32 value = atoi(str);
|
---|
| | 275 | this->ai_config->SetSetting(config_item.name, value);
|
---|
| | 276 | this->SetDirty();
|
---|
| | 277 | }
|
---|
| | 278 |
|
---|
| | 279 | virtual void OnDropdownSelect(int widget, int index)
|
---|
| | 280 | {
|
---|
| | 281 | assert(this->clicked_dropdown);
|
---|
| | 282 | VisibleSettingsList::const_iterator it = this->visible_settings.begin();
|
---|
| | 283 | for (int i = 0; i < this->clicked_row; i++) it++;
|
---|
| | 284 | const ScriptConfigItem config_item = **it;
|
---|
| | 285 | if (_game_mode != GM_MENU && !IsConsideredDead(this->slot) && (config_item.flags & SCRIPTCONFIG_INGAME) == 0) return;
|
---|
| | 286 | this->ai_config->SetSetting(config_item.name, index);
|
---|
| | 287 | this->SetDirty();
|
---|
| | 288 | }
|
---|
| | 289 |
|
---|
| | 290 | virtual void OnDropdownClose(Point pt, int widget, int index, bool instant_close)
|
---|
| | 291 | {
|
---|
| | 292 | /* We cannot raise the dropdown button just yet. OnClick needs some hint, whether
|
---|
| | 293 | * the same dropdown button was clicked again, and then not open the dropdown again.
|
---|
| | 294 | * So, we only remember that it was closed, and process it on the next OnPaint, which is
|
---|
| | 295 | * after OnClick. */
|
---|
| | 296 | assert(this->clicked_dropdown);
|
---|
| | 297 | this->closing_dropdown = true;
|
---|
| | 298 | this->SetDirty();
|
---|
| | 299 | }
|
---|
| | 300 |
|
---|
| | 301 | virtual void OnResize()
|
---|
| | 302 | {
|
---|
| | 303 | this->vscroll->SetCapacityFromWidget(this, WID_AIS_BACKGROUND);
|
---|
| | 304 | }
|
---|
| | 305 |
|
---|
| | 306 | virtual void OnRealtimeTick(uint delta_ms)
|
---|
| | 307 | {
|
---|
| | 308 | if (this->timeout.Elapsed(delta_ms)) {
|
---|
| | 309 | this->clicked_button = -1;
|
---|
| | 310 | this->SetDirty();
|
---|
| | 311 | }
|
---|
| | 312 | }
|
---|
| | 313 |
|
---|
| | 314 | /**
|
---|
| | 315 | * Some data on this window has become invalid.
|
---|
| | 316 | * @param data Information about the changed data.
|
---|
| | 317 | * @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.
|
---|
| | 318 | */
|
---|
| | 319 | virtual void OnInvalidateData(int data = 0, bool gui_scope = true)
|
---|
| | 320 | {
|
---|
| | 321 | this->RebuildVisibleSettings();
|
---|
| | 322 | HideDropDownMenu(this);
|
---|
| | 323 | DeleteChildWindows(WC_QUERY_STRING);
|
---|
| | 324 | }
|
---|
| | 325 |
|
---|
| | 326 | private:
|
---|
| | 327 | bool IsEditableItem(const ScriptConfigItem config_item) const
|
---|
| | 328 | {
|
---|
| | 329 | if (_game_mode == GM_MENU) return true;
|
---|
| | 330 |
|
---|
| | 331 | if (_game_mode == GM_NORMAL) {
|
---|
| | 332 | if (IsConsideredDead(slot)) return true;
|
---|
| | 333 | if (config_item.flags & SCRIPTCONFIG_INGAME) return true;
|
---|
| | 334 | }
|
---|
| | 335 |
|
---|
| | 336 | if (IsConsideredDead(slot)) {
|
---|
| | 337 | if (slot == OWNER_DEITY) {
|
---|
| | 338 | if (Game::GetInstance() == NULL) return true;
|
---|
| | 339 | }
|
---|
| | 340 | if (!Company::IsValidAiID(slot)) return true;
|
---|
| | 341 | if (Company::Get(slot)->ai_instance == NULL) return true;
|
---|
| | 342 | }
|
---|
| | 343 |
|
---|
| | 344 | return false;
|
---|
| | 345 | }
|
---|
| | 346 | }; |
---|