| 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 | }; |
|---|