changeset 8965:89de4625fe7d draft

(svn r12757) -Codechange: move all cheat related stuff from all over the place to a single location.
author rubidium <rubidium@openttd.org>
date Thu, 17 Apr 2008 21:21:01 +0000
parents ae064b8e200b
children b185cd12d66a
files projects/openttd_vs80.vcproj projects/openttd_vs90.vcproj source.list src/aircraft_cmd.cpp src/cheat.cpp src/cheat_func.h src/cheat_gui.cpp src/cheat_type.h src/gui.h src/industry_cmd.cpp src/industry_gui.cpp src/misc.cpp src/misc_gui.cpp src/openttd.cpp src/players.cpp src/road_cmd.cpp src/saveload.cpp src/toolbar_gui.cpp src/town_cmd.cpp src/tunnelbridge_cmd.cpp src/unmovable_cmd.cpp src/variables.h src/window.cpp
diffstat 23 files changed, 420 insertions(+), 285 deletions(-) [+]
line wrap: on
line diff
--- a/projects/openttd_vs80.vcproj
+++ b/projects/openttd_vs80.vcproj
@@ -492,6 +492,14 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\cheat.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\..\src\cheat_gui.cpp"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\command.cpp"
 				>
 			</File>
@@ -872,6 +880,14 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\cheat_func.h"
+				>
+			</File>
+			<File
+				RelativePath=".\..\src\cheat_type.h"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\currency.h"
 				>
 			</File>
@@ -896,7 +912,15 @@
 				>
 			</File>
 			<File
-				RelativePath=".\..\src\depot.h"
+				RelativePath=".\..\src\depot_base.h"
+				>
+			</File>
+			<File
+				RelativePath=".\..\src\depot_func.h"
+				>
+			</File>
+			<File
+				RelativePath=".\..\src\depot_map.h"
 				>
 			</File>
 			<File
--- a/projects/openttd_vs90.vcproj
+++ b/projects/openttd_vs90.vcproj
@@ -489,6 +489,14 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\cheat.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\..\src\cheat_gui.cpp"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\command.cpp"
 				>
 			</File>
@@ -869,6 +877,14 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\cheat_func.h"
+				>
+			</File>
+			<File
+				RelativePath=".\..\src\cheat_type.h"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\currency.h"
 				>
 			</File>
@@ -893,7 +909,15 @@
 				>
 			</File>
 			<File
-				RelativePath=".\..\src\depot.h"
+				RelativePath=".\..\src\depot_base.h"
+				>
+			</File>
+			<File
+				RelativePath=".\..\src\depot_func.h"
+				>
+			</File>
+			<File
+				RelativePath=".\..\src\depot_map.h"
 				>
 			</File>
 			<File
--- a/source.list
+++ b/source.list
@@ -9,6 +9,8 @@
 callback_table.cpp
 cargopacket.cpp
 cargotype.cpp
+cheat.cpp
+cheat_gui.cpp
 command.cpp
 console.cpp
 console_cmds.cpp
@@ -139,13 +141,17 @@
 command_func.h
 command_type.h
 console.h
+cheat_func.h
+cheat_type.h
 currency.h
 date_func.h
 date_type.h
 debug.h
 video/dedicated_v.h
 ai/default/default.h
-depot.h
+depot_base.h
+depot_func.h
+depot_map.h
 depot_type.h
 direction_func.h
 direction_type.h
--- a/src/aircraft_cmd.cpp
+++ b/src/aircraft_cmd.cpp
@@ -29,6 +29,7 @@
 #include "sound_func.h"
 #include "functions.h"
 #include "variables.h"
+#include "cheat_func.h"
 #include "autoreplace_func.h"
 #include "autoreplace_gui.h"
 #include "gfx_func.h"
new file mode 100644
--- /dev/null
+++ b/src/cheat.cpp
@@ -0,0 +1,57 @@
+/* $Id$ */
+
+/** @file misc.cpp */
+
+#include "stdafx.h"
+#include "saveload.h"
+#include "cheat_type.h"
+
+Cheats _cheats;
+
+void InitializeCheats()
+{
+	memset(&_cheats, 0, sizeof(Cheats));
+}
+
+static void Save_CHTS()
+{
+	/* Cannot use lengthof because _cheats is of type Cheats, not Cheat */
+	byte count = sizeof(_cheats) / sizeof(Cheat);
+	Cheat *cht = (Cheat*) &_cheats;
+	Cheat *cht_last = &cht[count];
+
+	SlSetLength(count * 2);
+	for (; cht != cht_last; cht++) {
+		SlWriteByte(cht->been_used);
+		SlWriteByte(cht->value);
+	}
+}
+
+static void Load_CHTS()
+{
+	Cheat *cht = (Cheat*)&_cheats;
+	uint count = SlGetFieldLength() / 2;
+
+	for (uint i = 0; i < count; i++) {
+		cht[i].been_used = (SlReadByte() != 0);
+		cht[i].value     = (SlReadByte() != 0);
+	}
+}
+
+bool CheatHasBeenUsed()
+{
+	/* Cannot use lengthof because _cheats is of type Cheats, not Cheat */
+	const Cheat* cht = (Cheat*)&_cheats;
+	const Cheat* cht_last = &cht[sizeof(_cheats) / sizeof(Cheat)];
+
+	for (; cht != cht_last; cht++) {
+		if (cht->been_used) return true;
+	}
+
+	return false;
+}
+
+
+extern const ChunkHandler _cheat_chunk_handlers[] = {
+	{ 'CHTS', Save_CHTS,     Load_CHTS,     CH_RIFF | CH_LAST}
+};
new file mode 100644
--- /dev/null
+++ b/src/cheat_func.h
@@ -0,0 +1,20 @@
+/* $Id$ */
+
+/** @file cheat_func.h Functions related to cheating. */
+
+#ifndef CHEAT_FUNC_H
+#define CHEAT_FUNC_H
+
+#include "cheat_type.h"
+
+extern Cheats _cheats;
+
+void ShowCheatWindow();
+
+/**
+ * Return true if any cheat has been used, false otherwise
+ * @return has a cheat been used?
+ */
+bool CheatHasBeenUsed();
+
+#endif /* CHEAT_FUNC_H */
new file mode 100644
--- /dev/null
+++ b/src/cheat_gui.cpp
@@ -0,0 +1,233 @@
+/* $Id$ */
+
+/** @file misc_gui.cpp */
+
+#include "stdafx.h"
+#include "openttd.h"
+#include "command_func.h"
+#include "cheat_func.h"
+#include "player_base.h"
+#include "player_func.h"
+#include "gfx_func.h"
+#include "date_func.h"
+#include "saveload.h"
+#include "window_gui.h"
+#include "newgrf.h"
+#include "settings_type.h"
+#include "strings_func.h"
+#include "window_func.h"
+#include "rail_gui.h"
+#include "gui.h"
+#include "player_gui.h"
+
+#include "table/strings.h"
+#include "table/sprites.h"
+
+
+/**
+ * The 'amount' to cheat with.
+ * This variable is semantically a constant value, but because the cheat
+ * code requires to be able to write to the variable it is not constified.
+ */
+static int32 _money_cheat_amount = 10000000;
+
+static int32 ClickMoneyCheat(int32 p1, int32 p2)
+{
+	DoCommandP(0, (uint32)(p2 * _money_cheat_amount), 0, NULL, CMD_MONEY_CHEAT);
+	return _money_cheat_amount;
+}
+
+/**
+ * @param p1 player to set to
+ * @param p2 is -1 or +1 (down/up)
+ */
+static int32 ClickChangePlayerCheat(int32 p1, int32 p2)
+{
+	while (IsValidPlayer((PlayerID)p1)) {
+		if (_players[p1].is_active) {
+			SetLocalPlayer((PlayerID)p1);
+
+			MarkWholeScreenDirty();
+			return _local_player;
+		}
+		p1 += p2;
+	}
+
+	return _local_player;
+}
+
+/**
+ * @param p1 -1 or +1 (down/up)
+ * @param p2 unused
+ */
+static int32 ClickChangeClimateCheat(int32 p1, int32 p2)
+{
+	if (p1 == -1) p1 = 3;
+	if (p1 ==  4) p1 = 0;
+	_opt.landscape = p1;
+	ReloadNewGRFData();
+	return _opt.landscape;
+}
+
+extern void EnginesMonthlyLoop();
+
+/**
+ * @param p1 unused
+ * @param p2 1 (increase) or -1 (decrease)
+ */
+static int32 ClickChangeDateCheat(int32 p1, int32 p2)
+{
+	YearMonthDay ymd;
+	ConvertDateToYMD(_date, &ymd);
+
+	if ((ymd.year == MIN_YEAR && p2 == -1) || (ymd.year == MAX_YEAR && p2 == 1)) return _cur_year;
+
+	SetDate(ConvertYMDToDate(_cur_year + p2, ymd.month, ymd.day));
+	EnginesMonthlyLoop();
+	SetWindowDirty(FindWindowById(WC_STATUS_BAR, 0));
+	ResetSignalVariant();
+	return _cur_year;
+}
+
+typedef int32 CheckButtonClick(int32, int32);
+
+struct CheatEntry {
+	VarType type;          ///< type of selector
+	StringID str;          ///< string with descriptive text
+	void *variable;        ///< pointer to the variable
+	bool *been_used;       ///< has this cheat been used before?
+	CheckButtonClick *proc;///< procedure
+};
+
+static const CheatEntry _cheats_ui[] = {
+	{SLE_INT32, STR_CHEAT_MONEY,           &_money_cheat_amount,            &_cheats.money.been_used,            &ClickMoneyCheat        },
+	{SLE_UINT8, STR_CHEAT_CHANGE_PLAYER,   &_local_player,                  &_cheats.switch_player.been_used,    &ClickChangePlayerCheat },
+	{SLE_BOOL,  STR_CHEAT_EXTRA_DYNAMITE,  &_cheats.magic_bulldozer.value,  &_cheats.magic_bulldozer.been_used,  NULL                    },
+	{SLE_BOOL,  STR_CHEAT_CROSSINGTUNNELS, &_cheats.crossing_tunnels.value, &_cheats.crossing_tunnels.been_used, NULL                    },
+	{SLE_BOOL,  STR_CHEAT_BUILD_IN_PAUSE,  &_cheats.build_in_pause.value,   &_cheats.build_in_pause.been_used,   NULL                    },
+	{SLE_BOOL,  STR_CHEAT_NO_JETCRASH,     &_cheats.no_jetcrash.value,      &_cheats.no_jetcrash.been_used,      NULL                    },
+	{SLE_BOOL,  STR_CHEAT_SETUP_PROD,      &_cheats.setup_prod.value,       &_cheats.setup_prod.been_used,       NULL                    },
+	{SLE_UINT8, STR_CHEAT_SWITCH_CLIMATE,  &_opt.landscape,                 &_cheats.switch_climate.been_used,   &ClickChangeClimateCheat},
+	{SLE_INT32, STR_CHEAT_CHANGE_DATE,     &_cur_year,                      &_cheats.change_date.been_used,      &ClickChangeDateCheat   },
+};
+
+
+static const Widget _cheat_widgets[] = {
+{   WWT_CLOSEBOX,   RESIZE_NONE,    14,     0,    10,     0,    13, STR_00C5,   STR_018B_CLOSE_WINDOW},
+{    WWT_CAPTION,   RESIZE_NONE,    14,    11,   399,     0,    13, STR_CHEATS, STR_018C_WINDOW_TITLE_DRAG_THIS},
+{      WWT_PANEL,   RESIZE_NONE,    14,     0,   399,    14,   169, 0x0,        STR_NULL},
+{      WWT_PANEL,   RESIZE_NONE,    14,     0,   399,    14,   169, 0x0,        STR_CHEATS_TIP},
+{   WIDGETS_END},
+};
+
+static void CheatsWndProc(Window *w, WindowEvent *e)
+{
+	switch (e->event) {
+		case WE_PAINT: {
+			int clk = WP(w, def_d).data_1;
+
+			DrawWindowWidgets(w);
+			DrawStringMultiCenter(200, 25, STR_CHEATS_WARNING, w->width - 50);
+
+			for (int i = 0, x = 0, y = 45; i != lengthof(_cheats_ui); i++) {
+				const CheatEntry *ce = &_cheats_ui[i];
+
+				DrawSprite((*ce->been_used) ? SPR_BOX_CHECKED : SPR_BOX_EMPTY, PAL_NONE, x + 5, y + 2);
+
+				switch (ce->type) {
+					case SLE_BOOL: {
+						bool on = (*(bool*)ce->variable);
+
+						DrawFrameRect(x + 20, y + 1, x + 30 + 9, y + 9, on ? 6 : 4, on ? FR_LOWERED : FR_NONE);
+						SetDParam(0, on ? STR_CONFIG_PATCHES_ON : STR_CONFIG_PATCHES_OFF);
+					} break;
+
+					default: {
+						int32 val = (int32)ReadValue(ce->variable, ce->type);
+						char buf[512];
+
+						/* Draw [<][>] boxes for settings of an integer-type */
+						DrawArrowButtons(x + 20, y, 3, clk - (i * 2), true, true);
+
+						switch (ce->str) {
+							/* Display date for change date cheat */
+							case STR_CHEAT_CHANGE_DATE: SetDParam(0, _date); break;
+
+							/* Draw colored flag for change player cheat */
+							case STR_CHEAT_CHANGE_PLAYER:
+								SetDParam(0, val);
+								GetString(buf, STR_CHEAT_CHANGE_PLAYER, lastof(buf));
+								DrawPlayerIcon(_current_player, 60 + GetStringBoundingBox(buf).width, y + 2);
+								break;
+
+							/* Set correct string for switch climate cheat */
+							case STR_CHEAT_SWITCH_CLIMATE: val += STR_TEMPERATE_LANDSCAPE;
+
+							/* Fallthrough */
+							default: SetDParam(0, val);
+						}
+					} break;
+				}
+
+				DrawString(50, y + 1, ce->str, TC_FROMSTRING);
+
+				y += 12;
+			}
+			break;
+		}
+
+		case WE_CLICK: {
+			uint btn = (e->we.click.pt.y - 46) / 12;
+			uint x = e->we.click.pt.x;
+
+			/* Not clicking a button? */
+			if (!IsInsideMM(x, 20, 40) || btn >= lengthof(_cheats_ui)) break;
+
+			const CheatEntry *ce = &_cheats_ui[btn];
+			int value = (int32)ReadValue(ce->variable, ce->type);
+			int oldvalue = value;
+
+			*ce->been_used = true;
+
+			switch (ce->type) {
+				case SLE_BOOL:
+					value ^= 1;
+					if (ce->proc != NULL) ce->proc(value, 0);
+					break;
+
+				default:
+					/* Take whatever the function returns */
+					value = ce->proc(value + ((x >= 30) ? 1 : -1), (x >= 30) ? 1 : -1);
+
+					if (value != oldvalue) WP(w, def_d).data_1 = btn * 2 + 1 + ((x >= 30) ? 1 : 0);
+					break;
+			}
+
+			if (value != oldvalue) WriteValue(ce->variable, ce->type, (int64)value);
+
+			w->flags4 |= 5 << WF_TIMEOUT_SHL;
+
+			SetWindowDirty(w);
+		} break;
+
+		case WE_TIMEOUT:
+			WP(w, def_d).data_1 = 0;
+			SetWindowDirty(w);
+			break;
+	}
+}
+
+static const WindowDesc _cheats_desc = {
+	240, 22, 400, 170, 400, 170,
+	WC_CHEATS, WC_NONE,
+	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
+	_cheat_widgets,
+	CheatsWndProc
+};
+
+
+void ShowCheatWindow()
+{
+	DeleteWindowById(WC_CHEATS, 0);
+	AllocateWindowDesc(&_cheats_desc);
+}
new file mode 100644
--- /dev/null
+++ b/src/cheat_type.h
@@ -0,0 +1,36 @@
+/* $Id$ */
+
+/** @file cheat_type.h Types related to cheating. */
+
+#ifndef CHEAT_TYPE_H
+#define CHEAT_TYPE_H
+
+/**
+ * Info about each of the cheats.
+ */
+struct Cheat {
+	bool been_used; ///< has this cheat been used before?
+	bool value;     ///< tells if the bool cheat is active or not
+};
+
+/**
+ * WARNING! Do _not_ remove entries in Cheats struct or change the order
+ * of the existing ones! Would break downward compatibility.
+ * Only add new entries at the end of the struct!
+ */
+struct Cheats {
+	Cheat magic_bulldozer;  ///< dynamite industries, unmovables
+	Cheat switch_player;    ///< change to another player
+	Cheat money;            ///< get rich or poor
+	Cheat crossing_tunnels; ///< allow tunnels that cross each other
+	Cheat build_in_pause;   ///< build while in pause mode
+	Cheat no_jetcrash;      ///< no jet will crash on small airports anymore
+	Cheat switch_climate;   ///< change the climate of the map
+	Cheat change_date;      ///< changes date ingame
+	Cheat setup_prod;       ///< setup raw-material production in game
+	Cheat dummy;            ///< empty cheat (enable running el-engines on normal rail)
+};
+
+extern Cheats _cheats;
+
+#endif /* CHEAT_TYPE_H */
--- a/src/gui.h
+++ b/src/gui.h
@@ -104,8 +104,6 @@
 void SetVScroll2Count(Window *w, int num);
 void SetHScrollCount(Window *w, int num);
 
-void ShowCheatWindow();
-
 void BuildFileList();
 void SetFiosType(const byte fiostype);
 
--- a/src/industry_cmd.cpp
+++ b/src/industry_cmd.cpp
@@ -16,6 +16,7 @@
 #include "news_func.h"
 #include "saveload.h"
 #include "variables.h"
+#include "cheat_func.h"
 #include "genworld.h"
 #include "water_map.h"
 #include "tree_map.h"
--- a/src/industry_gui.cpp
+++ b/src/industry_gui.cpp
@@ -14,6 +14,7 @@
 #include "industry.h"
 #include "town.h"
 #include "variables.h"
+#include "cheat_func.h"
 #include "cargotype.h"
 #include "newgrf.h"
 #include "newgrf_callbacks.h"
--- a/src/misc.cpp
+++ b/src/misc.cpp
@@ -10,6 +10,7 @@
 #include "saveload.h"
 #include "vehicle_gui.h"
 #include "variables.h"
+#include "cheat_func.h"
 #include "ai/ai.h"
 #include "newgrf_house.h"
 #include "cargotype.h"
@@ -50,7 +51,7 @@
 void InitializeCargoPackets();
 static void InitializeNameMgr();
 void InitializePlayers();
-static void InitializeCheats();
+void InitializeCheats();
 void InitializeNPF();
 
 void InitializeGame(int mode, uint size_x, uint size_y)
@@ -117,12 +118,6 @@
 }
 
 
-static void InitializeCheats()
-{
-	memset(&_cheats, 0, sizeof(Cheats));
-}
-
-
 static void InitializeNameMgr()
 {
 	memset(_name_array, 0, sizeof(_name_array));
@@ -464,31 +459,6 @@
 	}
 }
 
-static void Save_CHTS()
-{
-	byte count = sizeof(_cheats)/sizeof(Cheat);
-	Cheat* cht = (Cheat*) &_cheats;
-	Cheat* cht_last = &cht[count];
-
-	SlSetLength(count * 2);
-	for (; cht != cht_last; cht++) {
-		SlWriteByte(cht->been_used);
-		SlWriteByte(cht->value);
-	}
-}
-
-static void Load_CHTS()
-{
-	Cheat* cht = (Cheat*)&_cheats;
-	uint count = SlGetFieldLength() / 2;
-
-	for (uint i = 0; i < count; i++) {
-		cht[i].been_used = (SlReadByte() != 0);
-		cht[i].value     = (SlReadByte() != 0);
-	}
-}
-
-
 extern const ChunkHandler _misc_chunk_handlers[] = {
 	{ 'MAPS', Save_MAPS,     Load_MAPS,     CH_RIFF },
 	{ 'MAPT', Save_MAPT,     Load_MAPT,     CH_RIFF },
@@ -502,6 +472,5 @@
 
 	{ 'NAME', NULL,          Load_NAME,     CH_ARRAY},
 	{ 'DATE', SaveLoad_DATE, SaveLoad_DATE, CH_RIFF},
-	{ 'VIEW', SaveLoad_VIEW, SaveLoad_VIEW, CH_RIFF},
-	{ 'CHTS', Save_CHTS,     Load_CHTS,     CH_RIFF | CH_LAST}
+	{ 'VIEW', SaveLoad_VIEW, SaveLoad_VIEW, CH_RIFF | CH_LAST},
 };
--- a/src/misc_gui.cpp
+++ b/src/misc_gui.cpp
@@ -24,6 +24,7 @@
 #include "town.h"
 #include "network/network.h"
 #include "variables.h"
+#include "cheat_func.h"
 #include "train.h"
 #include "tgp.h"
 #include "cargotype.h"
@@ -1788,211 +1789,3 @@
 			break;
 	}
 }
-
-/**
- * The 'amount' to cheat with.
- * This variable is semantically a constant value, but because the cheat
- * code requires to be able to write to the variable it is not constified.
- */
-static int32 _money_cheat_amount = 10000000;
-
-static int32 ClickMoneyCheat(int32 p1, int32 p2)
-{
-	DoCommandP(0, (uint32)(p2 * _money_cheat_amount), 0, NULL, CMD_MONEY_CHEAT);
-	return _money_cheat_amount;
-}
-
-/**
- * @param p1 player to set to
- * @param p2 is -1 or +1 (down/up)
- */
-static int32 ClickChangePlayerCheat(int32 p1, int32 p2)
-{
-	while (IsValidPlayer((PlayerID)p1)) {
-		if (_players[p1].is_active) {
-			SetLocalPlayer((PlayerID)p1);
-
-			MarkWholeScreenDirty();
-			return _local_player;
-		}
-		p1 += p2;
-	}
-
-	return _local_player;
-}
-
-/**
- * @param p1 -1 or +1 (down/up)
- * @param p2 unused
- */
-static int32 ClickChangeClimateCheat(int32 p1, int32 p2)
-{
-	if (p1 == -1) p1 = 3;
-	if (p1 ==  4) p1 = 0;
-	_opt.landscape = p1;
-	ReloadNewGRFData();
-	return _opt.landscape;
-}
-
-extern void EnginesMonthlyLoop();
-
-/**
- * @param p1 unused
- * @param p2 1 (increase) or -1 (decrease)
- */
-static int32 ClickChangeDateCheat(int32 p1, int32 p2)
-{
-	YearMonthDay ymd;
-	ConvertDateToYMD(_date, &ymd);
-
-	if ((ymd.year == MIN_YEAR && p2 == -1) || (ymd.year == MAX_YEAR && p2 == 1)) return _cur_year;
-
-	SetDate(ConvertYMDToDate(_cur_year + p2, ymd.month, ymd.day));
-	EnginesMonthlyLoop();
-	SetWindowDirty(FindWindowById(WC_STATUS_BAR, 0));
-	ResetSignalVariant();
-	return _cur_year;
-}
-
-typedef int32 CheckButtonClick(int32, int32);
-
-struct CheatEntry {
-	VarType type;          ///< type of selector
-	StringID str;          ///< string with descriptive text
-	void *variable;        ///< pointer to the variable
-	bool *been_used;       ///< has this cheat been used before?
-	CheckButtonClick *proc;///< procedure
-};
-
-static const CheatEntry _cheats_ui[] = {
-	{SLE_INT32, STR_CHEAT_MONEY,           &_money_cheat_amount,            &_cheats.money.been_used,            &ClickMoneyCheat        },
-	{SLE_UINT8, STR_CHEAT_CHANGE_PLAYER,   &_local_player,                  &_cheats.switch_player.been_used,    &ClickChangePlayerCheat },
-	{SLE_BOOL,  STR_CHEAT_EXTRA_DYNAMITE,  &_cheats.magic_bulldozer.value,  &_cheats.magic_bulldozer.been_used,  NULL                    },
-	{SLE_BOOL,  STR_CHEAT_CROSSINGTUNNELS, &_cheats.crossing_tunnels.value, &_cheats.crossing_tunnels.been_used, NULL                    },
-	{SLE_BOOL,  STR_CHEAT_BUILD_IN_PAUSE,  &_cheats.build_in_pause.value,   &_cheats.build_in_pause.been_used,   NULL                    },
-	{SLE_BOOL,  STR_CHEAT_NO_JETCRASH,     &_cheats.no_jetcrash.value,      &_cheats.no_jetcrash.been_used,      NULL                    },
-	{SLE_BOOL,  STR_CHEAT_SETUP_PROD,      &_cheats.setup_prod.value,       &_cheats.setup_prod.been_used,       NULL                    },
-	{SLE_UINT8, STR_CHEAT_SWITCH_CLIMATE,  &_opt.landscape,                 &_cheats.switch_climate.been_used,   &ClickChangeClimateCheat},
-	{SLE_INT32, STR_CHEAT_CHANGE_DATE,     &_cur_year,                      &_cheats.change_date.been_used,      &ClickChangeDateCheat   },
-};
-
-
-static const Widget _cheat_widgets[] = {
-{   WWT_CLOSEBOX,   RESIZE_NONE,    14,     0,    10,     0,    13, STR_00C5,   STR_018B_CLOSE_WINDOW},
-{    WWT_CAPTION,   RESIZE_NONE,    14,    11,   399,     0,    13, STR_CHEATS, STR_018C_WINDOW_TITLE_DRAG_THIS},
-{      WWT_PANEL,   RESIZE_NONE,    14,     0,   399,    14,   169, 0x0,        STR_NULL},
-{      WWT_PANEL,   RESIZE_NONE,    14,     0,   399,    14,   169, 0x0,        STR_CHEATS_TIP},
-{   WIDGETS_END},
-};
-
-static void CheatsWndProc(Window *w, WindowEvent *e)
-{
-	switch (e->event) {
-		case WE_PAINT: {
-			int clk = WP(w, def_d).data_1;
-
-			DrawWindowWidgets(w);
-			DrawStringMultiCenter(200, 25, STR_CHEATS_WARNING, w->width - 50);
-
-			for (int i = 0, x = 0, y = 45; i != lengthof(_cheats_ui); i++) {
-				const CheatEntry *ce = &_cheats_ui[i];
-
-				DrawSprite((*ce->been_used) ? SPR_BOX_CHECKED : SPR_BOX_EMPTY, PAL_NONE, x + 5, y + 2);
-
-				switch (ce->type) {
-					case SLE_BOOL: {
-						bool on = (*(bool*)ce->variable);
-
-						DrawFrameRect(x + 20, y + 1, x + 30 + 9, y + 9, on ? 6 : 4, on ? FR_LOWERED : FR_NONE);
-						SetDParam(0, on ? STR_CONFIG_PATCHES_ON : STR_CONFIG_PATCHES_OFF);
-					} break;
-
-					default: {
-						int32 val = (int32)ReadValue(ce->variable, ce->type);
-						char buf[512];
-
-						/* Draw [<][>] boxes for settings of an integer-type */
-						DrawArrowButtons(x + 20, y, 3, clk - (i * 2), true, true);
-
-						switch (ce->str) {
-							/* Display date for change date cheat */
-							case STR_CHEAT_CHANGE_DATE: SetDParam(0, _date); break;
-
-							/* Draw colored flag for change player cheat */
-							case STR_CHEAT_CHANGE_PLAYER:
-								SetDParam(0, val);
-								GetString(buf, STR_CHEAT_CHANGE_PLAYER, lastof(buf));
-								DrawPlayerIcon(_current_player, 60 + GetStringBoundingBox(buf).width, y + 2);
-								break;
-
-							/* Set correct string for switch climate cheat */
-							case STR_CHEAT_SWITCH_CLIMATE: val += STR_TEMPERATE_LANDSCAPE;
-
-							/* Fallthrough */
-							default: SetDParam(0, val);
-						}
-					} break;
-				}
-
-				DrawString(50, y + 1, ce->str, TC_FROMSTRING);
-
-				y += 12;
-			}
-			break;
-		}
-
-		case WE_CLICK: {
-			uint btn = (e->we.click.pt.y - 46) / 12;
-			uint x = e->we.click.pt.x;
-
-			/* Not clicking a button? */
-			if (!IsInsideMM(x, 20, 40) || btn >= lengthof(_cheats_ui)) break;
-
-			const CheatEntry *ce = &_cheats_ui[btn];
-			int value = (int32)ReadValue(ce->variable, ce->type);
-			int oldvalue = value;
-
-			*ce->been_used = true;
-
-			switch (ce->type) {
-				case SLE_BOOL:
-					value ^= 1;
-					if (ce->proc != NULL) ce->proc(value, 0);
-					break;
-
-				default:
-					/* Take whatever the function returns */
-					value = ce->proc(value + ((x >= 30) ? 1 : -1), (x >= 30) ? 1 : -1);
-
-					if (value != oldvalue) WP(w, def_d).data_1 = btn * 2 + 1 + ((x >= 30) ? 1 : 0);
-					break;
-			}
-
-			if (value != oldvalue) WriteValue(ce->variable, ce->type, (int64)value);
-
-			w->flags4 |= 5 << WF_TIMEOUT_SHL;
-
-			SetWindowDirty(w);
-		} break;
-
-		case WE_TIMEOUT:
-			WP(w, def_d).data_1 = 0;
-			SetWindowDirty(w);
-			break;
-	}
-}
-
-static const WindowDesc _cheats_desc = {
-	240, 22, 400, 170, 400, 170,
-	WC_CHEATS, WC_NONE,
-	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
-	_cheat_widgets,
-	CheatsWndProc
-};
-
-
-void ShowCheatWindow()
-{
-	DeleteWindowById(WC_CHEATS, 0);
-	AllocateWindowDesc(&_cheats_desc);
-}
--- a/src/openttd.cpp
+++ b/src/openttd.cpp
@@ -57,6 +57,7 @@
 #include "strings_func.h"
 #include "date_func.h"
 #include "vehicle_func.h"
+#include "cheat_func.h"
 
 #include "newgrf.h"
 #include "newgrf_config.h"
--- a/src/players.cpp
+++ b/src/players.cpp
@@ -14,6 +14,7 @@
 #include "network/network.h"
 #include "network/network_internal.h"
 #include "variables.h"
+#include "cheat_func.h"
 #include "ai/ai.h"
 #include "player_face.h"
 #include "group.h"
@@ -956,19 +957,6 @@
 	return _endgame_perf_titles[value];
 }
 
-/** Return true if any cheat has been used, false otherwise */
-static bool CheatHasBeenUsed()
-{
-	const Cheat* cht = (Cheat*)&_cheats;
-	const Cheat* cht_last = &cht[sizeof(_cheats) / sizeof(Cheat)];
-
-	for (; cht != cht_last; cht++) {
-		if (cht->been_used) return true;
-	}
-
-	return false;
-}
-
 /** Save the highscore for the player */
 int8 SaveHighScoreValue(const Player *p)
 {
--- a/src/road_cmd.cpp
+++ b/src/road_cmd.cpp
@@ -35,6 +35,7 @@
 #include "sound_func.h"
 #include "road_func.h"
 #include "tunnelbridge.h"
+#include "cheat_func.h"
 
 #include "table/sprites.h"
 #include "table/strings.h"
--- a/src/saveload.cpp
+++ b/src/saveload.cpp
@@ -1248,6 +1248,7 @@
 
 /* these define the chunks */
 extern const ChunkHandler _misc_chunk_handlers[];
+extern const ChunkHandler _cheat_chunk_handlers[] ;
 extern const ChunkHandler _setting_chunk_handlers[];
 extern const ChunkHandler _player_chunk_handlers[];
 extern const ChunkHandler _engine_chunk_handlers[];
@@ -1267,6 +1268,7 @@
 
 static const ChunkHandler * const _chunk_handlers[] = {
 	_misc_chunk_handlers,
+	_cheat_chunk_handlers,
 	_setting_chunk_handlers,
 	_veh_chunk_handlers,
 	_waypoint_chunk_handlers,
--- a/src/toolbar_gui.cpp
+++ b/src/toolbar_gui.cpp
@@ -28,6 +28,7 @@
 #include "toolbar_gui.h"
 #include "vehicle_base.h"
 #include "gfx_func.h"
+#include "cheat_func.h"
 
 #include "network/network.h"
 
--- a/src/town_cmd.cpp
+++ b/src/town_cmd.cpp
@@ -44,6 +44,7 @@
 #include "sprite.h"
 #include "economy_func.h"
 #include "station_func.h"
+#include "cheat_func.h"
 
 #include "table/strings.h"
 #include "table/sprites.h"
--- a/src/tunnelbridge_cmd.cpp
+++ b/src/tunnelbridge_cmd.cpp
@@ -37,6 +37,7 @@
 #include "engine_func.h"
 #include "economy_func.h"
 #include "rail.h"
+#include "cheat_func.h"
 
 #include "table/sprites.h"
 #include "table/strings.h"
--- a/src/unmovable_cmd.cpp
+++ b/src/unmovable_cmd.cpp
@@ -26,6 +26,7 @@
 #include "player_gui.h"
 #include "station_type.h"
 #include "economy_func.h"
+#include "cheat_func.h"
 
 #include "table/strings.h"
 #include "table/sprites.h"
--- a/src/variables.h
+++ b/src/variables.h
@@ -39,31 +39,6 @@
 VARDEF int _saved_scrollpos_x;
 VARDEF int _saved_scrollpos_y;
 
-struct Cheat {
-	bool been_used; // has this cheat been used before?
-	bool value;     // tells if the bool cheat is active or not
-};
-
-
-/* WARNING! Do _not_ remove entries in Cheats struct or change the order
- * of the existing ones! Would break downward compatibility.
- * Only add new entries at the end of the struct! */
-
-struct Cheats {
-	Cheat magic_bulldozer;  // dynamite industries, unmovables
-	Cheat switch_player;    // change to another player
-	Cheat money;            // get rich
-	Cheat crossing_tunnels; // allow tunnels that cross each other
-	Cheat build_in_pause;   // build while in pause mode
-	Cheat no_jetcrash;      // no jet will crash on small airports anymore
-	Cheat switch_climate;
-	Cheat change_date;      // changes date ingame
-	Cheat setup_prod;       // setup raw-material production in game
-	Cheat dummy;            // empty cheat (enable running el-engines on normal rail)
-};
-
-VARDEF Cheats _cheats;
-
 /* NOSAVE: Used in palette animations only, not really important. */
 VARDEF int _palette_animation_counter;
 
--- a/src/window.cpp
+++ b/src/window.cpp
@@ -19,6 +19,7 @@
 #include "map_func.h"
 #include "vehicle_base.h"
 #include "settings_type.h"
+#include "cheat_func.h"
 
 #include "table/sprites.h"