diff --git a/src/ai/ai_gui.cpp b/src/ai/ai_gui.cpp index debed35..24d1575 100644 --- a/src/ai/ai_gui.cpp +++ b/src/ai/ai_gui.cpp @@ -11,6 +11,7 @@ #include "../stdafx.h" #include "../table/sprites.h" +#include "../cheat_type.h" #include "../gui.h" #include "../querystring_gui.h" #include "../company_func.h" @@ -751,12 +752,20 @@ void ShowAIConfigWindow() new AIConfigWindow(); } +/** See whether the AI is stoppable (cheat) */ +static inline bool isAIStopable() +{ + return _cheats.stop_ai.value; +} + /** Enum referring to the widgets of the AI debug window */ enum AIDebugWindowWidgets { AID_WIDGET_VIEW, AID_WIDGET_NAME_TEXT, AID_WIDGET_SETTINGS, AID_WIDGET_RELOAD_TOGGLE, + AID_WIDGET_STOP_AI_WIDGETS, + AID_WIDGET_STOP_AI, AID_WIDGET_LOG_PANEL, AID_WIDGET_SCROLLBAR, AID_WIDGET_COMPANY_BUTTON_START, @@ -799,6 +808,7 @@ struct AIDebugWindow : public QueryStringBaseWindow { this->vscroll = this->GetScrollbar(AID_WIDGET_SCROLLBAR); this->show_break_box = _settings_client.gui.ai_developer_tools; this->GetWidget(AID_BREAK_STRING_WIDGETS)->SetDisplayedPlane(this->show_break_box ? 0 : SZSP_HORIZONTAL); + this->GetWidget(AID_WIDGET_STOP_AI_WIDGETS)->SetDisplayedPlane(isAIStopable() ? 0 : SZSP_NONE); this->FinishInitNested(desc, number); if (!this->show_break_box) break_check_enabled = false; @@ -808,6 +818,7 @@ struct AIDebugWindow : public QueryStringBaseWindow { } this->DisableWidget(AID_WIDGET_RELOAD_TOGGLE); this->DisableWidget(AID_WIDGET_SETTINGS); + this->DisableWidget(AID_WIDGET_STOP_AI); this->DisableWidget(AID_WIDGET_CONTINUE_BTN); this->last_vscroll_pos = 0; @@ -856,11 +867,12 @@ struct AIDebugWindow : public QueryStringBaseWindow { } } } - - /* Update "Reload AI" and "AI settings" buttons */ + + /* Update "Reload AI", "Stop AI" and "AI settings" buttons */ this->SetWidgetsDisabledState(ai_debug_company == INVALID_COMPANY, AID_WIDGET_RELOAD_TOGGLE, AID_WIDGET_SETTINGS, + AID_WIDGET_STOP_AI, WIDGET_LIST_END); /* Draw standard stuff */ @@ -1035,6 +1047,11 @@ struct AIDebugWindow : public QueryStringBaseWindow { ShowAISettingsWindow(ai_debug_company); break; + case AID_WIDGET_STOP_AI: + /* Kill the company of the AI */ + DoCommandP(0, 2 | ai_debug_company << 16, 0, CMD_COMPANY_CTRL); + break; + case AID_WIDGET_BREAK_STR_ON_OFF_BTN: this->break_check_enabled = !this->break_check_enabled; this->SetWidgetLoweredState(AID_WIDGET_BREAK_STR_ON_OFF_BTN, this->break_check_enabled); @@ -1059,6 +1076,7 @@ struct AIDebugWindow : public QueryStringBaseWindow { { this->RaiseWidget(AID_WIDGET_RELOAD_TOGGLE); this->RaiseWidget(AID_WIDGET_SETTINGS); + this->RaiseWidget(AID_WIDGET_STOP_AI); this->SetDirty(); } @@ -1098,6 +1116,12 @@ struct AIDebugWindow : public QueryStringBaseWindow { } } + if(gui_scope && data == -3) + { + this->GetWidget(AID_WIDGET_STOP_AI_WIDGETS)->SetDisplayedPlane(isAIStopable() ? 0 : SZSP_NONE); + this->ReInit(); + } + /* If the log message is related to the active company tab, check the break string. * This needs to be done in gameloop-scope, so the AI is suspended immediately. */ if (!gui_scope && data == ai_debug_company && this->break_check_enabled && !StrEmpty(this->edit_str_buf)) { @@ -1160,6 +1184,10 @@ static const NWidgetPart _nested_ai_debug_widgets[] = { NWidget(WWT_TEXTBTN, COLOUR_GREY, AID_WIDGET_NAME_TEXT), SetFill(1, 0), SetResize(1, 0), SetDataTip(STR_JUST_STRING, STR_AI_DEBUG_NAME_TOOLTIP), NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, AID_WIDGET_SETTINGS), SetMinimalSize(100, 20), SetDataTip(STR_AI_DEBUG_SETTINGS, STR_AI_DEBUG_SETTINGS_TOOLTIP), NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, AID_WIDGET_RELOAD_TOGGLE), SetMinimalSize(100, 20), SetDataTip(STR_AI_DEBUG_RELOAD, STR_AI_DEBUG_RELOAD_TOOLTIP), + /* Stop AI button */ + NWidget(NWID_SELECTION, INVALID_COLOUR, AID_WIDGET_STOP_AI_WIDGETS), + NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, AID_WIDGET_STOP_AI), SetMinimalSize(100, 20), SetDataTip(STR_AI_DEBUG_STOP_AI, STR_AI_DEBUG_STOP_AI_TOOLTIP), + EndContainer(), EndContainer(), NWidget(NWID_HORIZONTAL), NWidget(NWID_VERTICAL), diff --git a/src/cheat_gui.cpp b/src/cheat_gui.cpp index b88a935..b603f56 100644 --- a/src/cheat_gui.cpp +++ b/src/cheat_gui.cpp @@ -73,10 +73,23 @@ static int32 ClickChangeCompanyCheat(int32 p1, int32 p2) } /** + * Allow (or disallow) stopping AI + * @param p1 new value + * @param p2 unused + * @return New value allowing stopping AI + */ +static int32 ClickStopAICheat(int32 p1, int32 p2) +{ + _cheats.stop_ai.value = (p1 != 0); + InvalidateWindowClassesData(WC_AI_DEBUG, -3); + return _cheats.stop_ai.value; +} + +/** * Allow (or disallow) changing production of all industries. * @param p1 new value * @param p2 unused - * @return New value allwing change of industry production. + * @return New value allowing change of industry production. */ static int32 ClickSetProdCheat(int32 p1, int32 p2) { @@ -140,7 +153,7 @@ enum CheatNumbers { CHT_SETUP_PROD, ///< Allow manually editing of industry production. CHT_SWITCH_CLIMATE, ///< Switch climate. CHT_CHANGE_DATE, ///< Do time traveling. - + CHT_STOP_AI, ///< Stop an AI. CHT_NUM_CHEATS, ///< Number of cheats. }; @@ -173,6 +186,7 @@ static const CheatEntry _cheats_ui[] = { {SLE_BOOL, STR_CHEAT_SETUP_PROD, &_cheats.setup_prod.value, &_cheats.setup_prod.been_used, &ClickSetProdCheat }, {SLE_UINT8, STR_CHEAT_SWITCH_CLIMATE, &_settings_game.game_creation.landscape, &_cheats.switch_climate.been_used, &ClickChangeClimateCheat }, {SLE_INT32, STR_CHEAT_CHANGE_DATE, &_cur_year, &_cheats.change_date.been_used, &ClickChangeDateCheat }, + {SLE_BOOL, STR_CHEAT_STOP_AI, &_cheats.stop_ai.value, &_cheats.stop_ai.been_used, &ClickStopAICheat }, }; assert_compile(CHT_NUM_CHEATS == lengthof(_cheats_ui)); @@ -227,6 +241,7 @@ struct CheatWindow : Window { DrawFrameRect(button_left, y + 1, button_left + 20 - 1, y + FONT_HEIGHT_NORMAL - 1, on ? COLOUR_GREEN : COLOUR_RED, on ? FR_LOWERED : FR_NONE); SetDParam(0, on ? STR_CONFIG_SETTING_ON : STR_CONFIG_SETTING_OFF); + break; } diff --git a/src/cheat_type.h b/src/cheat_type.h index 8cb438f..ea8bfba 100644 --- a/src/cheat_type.h +++ b/src/cheat_type.h @@ -36,6 +36,7 @@ struct Cheats { Cheat change_date; ///< changes date ingame Cheat setup_prod; ///< setup raw-material production in game Cheat dummy2; ///< empty cheat (enable running el-engines on normal rail) + Cheat stop_ai; ///< Stop an AI }; extern Cheats _cheats; diff --git a/src/lang/english.txt b/src/lang/english.txt index 090540f..c4d8923 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -1443,6 +1443,7 @@ STR_CHEAT_SWITCH_CLIMATE_TOYLAND_LANDSCAPE :Toyland landsca STR_CHEAT_CHANGE_DATE :{LTBLUE}Change date: {ORANGE}{DATE_SHORT} STR_CHEAT_CHANGE_DATE_QUERY_CAPT :{WHITE}Change current year STR_CHEAT_SETUP_PROD :{LTBLUE}Enable modifying production values: {ORANGE}{STRING1} +STR_CHEAT_STOP_AI :{LTBLUE}Enable stopping AIs: {ORANGE}{STRING1} # Livery window STR_LIVERY_CAPTION :{WHITE}New Colour Scheme @@ -3349,6 +3350,8 @@ STR_AI_DEBUG_NAME_AND_VERSION :{BLACK}{RAW_STR STR_AI_DEBUG_NAME_TOOLTIP :{BLACK}Name of the AI STR_AI_DEBUG_SETTINGS :{BLACK}AI Settings STR_AI_DEBUG_SETTINGS_TOOLTIP :{BLACK}Change the settings of the AI +STR_AI_DEBUG_STOP_AI :{BLACK}Stop AI +STR_AI_DEBUG_STOP_AI_TOOLTIP :{BLACK}Kill the AI STR_AI_DEBUG_RELOAD :{BLACK}Reload AI STR_AI_DEBUG_RELOAD_TOOLTIP :{BLACK}Kill the AI, reload the script, and restart the AI STR_AI_DEBUG_BREAK_STR_ON_OFF_TOOLTIP :{BLACK}Enable/disable breaking when an AI log message matches the break string diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp index 8933bae..a34e46b 100644 --- a/src/saveload/saveload.cpp +++ b/src/saveload/saveload.cpp @@ -228,8 +228,9 @@ * 161 22567 * 162 22713 * 163 22767 + * 164 22855 */ -extern const uint16 SAVEGAME_VERSION = 163; ///< Current savegame version of OpenTTD. +extern const uint16 SAVEGAME_VERSION = 164; ///< Current savegame version of OpenTTD. SavegameType _savegame_type; ///< type of savegame we are loading