2 * This file is part of OpenTTD.
3 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
8 /** @file misc_sl.cpp Saving and loading of things that didn't fit anywhere else */
10 #include "../stdafx.h"
13 #include "compat/misc_sl_compat.h"
15 #include "../timer/timer_game_calendar.h"
16 #include "../timer/timer_game_economy.h"
17 #include "../zoom_func.h"
18 #include "../window_gui.h"
19 #include "../window_func.h"
20 #include "../viewport_func.h"
21 #include "../gfx_func.h"
22 #include "../core/random_func.hpp"
24 #include "../timer/timer.h"
25 #include "../timer/timer_game_tick.h"
27 #include "../safeguards.h"
29 extern TileIndex _cur_tileloop_tile
;
30 extern uint16_t _disaster_delay
;
31 extern uint8_t _trees_tick_ctr
;
33 /* Keep track of current game position */
34 int _saved_scrollpos_x
;
35 int _saved_scrollpos_y
;
36 ZoomLevel _saved_scrollpos_zoom
;
38 void SaveViewportBeforeSaveGame()
40 /* Don't use GetMainWindow() in case the window does not exist. */
41 const Window
*w
= FindWindowById(WC_MAIN_WINDOW
, 0);
42 if (w
== nullptr || w
->viewport
== nullptr) {
43 /* Ensure saved position is clearly invalid. */
44 _saved_scrollpos_x
= INT_MAX
;
45 _saved_scrollpos_y
= INT_MAX
;
46 _saved_scrollpos_zoom
= ZOOM_LVL_END
;
48 _saved_scrollpos_x
= w
->viewport
->scrollpos_x
;
49 _saved_scrollpos_y
= w
->viewport
->scrollpos_y
;
50 _saved_scrollpos_zoom
= w
->viewport
->zoom
;
54 void ResetViewportAfterLoadGame()
56 Window
*w
= GetMainWindow();
58 w
->viewport
->scrollpos_x
= _saved_scrollpos_x
;
59 w
->viewport
->scrollpos_y
= _saved_scrollpos_y
;
60 w
->viewport
->dest_scrollpos_x
= _saved_scrollpos_x
;
61 w
->viewport
->dest_scrollpos_y
= _saved_scrollpos_y
;
63 Viewport
*vp
= w
->viewport
;
64 vp
->zoom
= std::min(_saved_scrollpos_zoom
, ZOOM_LVL_MAX
);
65 vp
->virtual_width
= ScaleByZoom(vp
->width
, vp
->zoom
);
66 vp
->virtual_height
= ScaleByZoom(vp
->height
, vp
->zoom
);
68 /* If zoom_max is ZOOM_LVL_MIN then the setting has not been loaded yet, therefore all levels are allowed. */
69 if (_settings_client
.gui
.zoom_max
!= ZOOM_LVL_MIN
) {
70 /* Ensure zoom level is allowed */
71 while (vp
->zoom
< _settings_client
.gui
.zoom_min
) DoZoomInOutWindow(ZOOM_OUT
, w
);
72 while (vp
->zoom
> _settings_client
.gui
.zoom_max
) DoZoomInOutWindow(ZOOM_IN
, w
);
75 DoZoomInOutWindow(ZOOM_NONE
, w
); // update button status
76 MarkWholeScreenDirty();
79 uint8_t _age_cargo_skip_counter
; ///< Skip aging of cargo? Used before savegame version 162.
80 extern TimeoutTimer
<TimerGameTick
> _new_competitor_timeout
;
82 static const SaveLoad _date_desc
[] = {
83 SLEG_CONDVAR("date", TimerGameCalendar::date
, SLE_FILE_U16
| SLE_VAR_I32
, SL_MIN_VERSION
, SLV_31
),
84 SLEG_CONDVAR("date", TimerGameCalendar::date
, SLE_INT32
, SLV_31
, SL_MAX_VERSION
),
85 SLEG_VAR("date_fract", TimerGameCalendar::date_fract
, SLE_UINT16
),
86 SLEG_CONDVAR("tick_counter", TimerGameTick::counter
, SLE_FILE_U16
| SLE_VAR_U64
, SL_MIN_VERSION
, SLV_U64_TICK_COUNTER
),
87 SLEG_CONDVAR("tick_counter", TimerGameTick::counter
, SLE_UINT64
, SLV_U64_TICK_COUNTER
, SL_MAX_VERSION
),
88 SLEG_CONDVAR("economy_date", TimerGameEconomy::date
, SLE_INT32
, SLV_ECONOMY_DATE
, SL_MAX_VERSION
),
89 SLEG_CONDVAR("economy_date_fract", TimerGameEconomy::date_fract
, SLE_UINT16
, SLV_ECONOMY_DATE
, SL_MAX_VERSION
),
90 SLEG_CONDVAR("calendar_sub_date_fract", TimerGameCalendar::sub_date_fract
, SLE_UINT16
, SLV_CALENDAR_SUB_DATE_FRACT
, SL_MAX_VERSION
),
91 SLEG_CONDVAR("age_cargo_skip_counter", _age_cargo_skip_counter
, SLE_UINT8
, SL_MIN_VERSION
, SLV_162
),
92 SLEG_CONDVAR("cur_tileloop_tile", _cur_tileloop_tile
, SLE_FILE_U16
| SLE_VAR_U32
, SL_MIN_VERSION
, SLV_6
),
93 SLEG_CONDVAR("cur_tileloop_tile", _cur_tileloop_tile
, SLE_UINT32
, SLV_6
, SL_MAX_VERSION
),
94 SLEG_VAR("next_disaster_start", _disaster_delay
, SLE_UINT16
),
95 SLEG_VAR("random_state[0]", _random
.state
[0], SLE_UINT32
),
96 SLEG_VAR("random_state[1]", _random
.state
[1], SLE_UINT32
),
97 SLEG_VAR("company_tick_counter", _cur_company_tick_index
, SLE_FILE_U8
| SLE_VAR_U32
),
98 SLEG_VAR("trees_tick_counter", _trees_tick_ctr
, SLE_UINT8
),
99 SLEG_CONDVAR("pause_mode", _pause_mode
, SLE_UINT8
, SLV_4
, SL_MAX_VERSION
),
100 SLEG_CONDSSTR("id", _game_session_stats
.savegame_id
, SLE_STR
, SLV_SAVEGAME_ID
, SL_MAX_VERSION
),
101 /* For older savegames, we load the current value as the "period"; afterload will set the "fired" and "elapsed". */
102 SLEG_CONDVAR("next_competitor_start", _new_competitor_timeout
.period
.value
, SLE_FILE_U16
| SLE_VAR_U32
, SL_MIN_VERSION
, SLV_109
),
103 SLEG_CONDVAR("next_competitor_start", _new_competitor_timeout
.period
.value
, SLE_UINT32
, SLV_109
, SLV_AI_START_DATE
),
104 SLEG_CONDVAR("competitors_interval", _new_competitor_timeout
.period
.value
, SLE_UINT32
, SLV_AI_START_DATE
, SL_MAX_VERSION
),
105 SLEG_CONDVAR("competitors_interval_elapsed", _new_competitor_timeout
.storage
.elapsed
, SLE_UINT32
, SLV_AI_START_DATE
, SL_MAX_VERSION
),
106 SLEG_CONDVAR("competitors_interval_fired", _new_competitor_timeout
.fired
, SLE_BOOL
, SLV_AI_START_DATE
, SL_MAX_VERSION
),
109 static const SaveLoad _date_check_desc
[] = {
110 SLEG_CONDVAR("date", _load_check_data
.current_date
, SLE_FILE_U16
| SLE_VAR_I32
, SL_MIN_VERSION
, SLV_31
),
111 SLEG_CONDVAR("date", _load_check_data
.current_date
, SLE_INT32
, SLV_31
, SL_MAX_VERSION
),
114 /* Save load date related variables as well as persistent tick counters
115 * XXX: currently some unrelated stuff is just put here */
116 struct DATEChunkHandler
: ChunkHandler
{
117 DATEChunkHandler() : ChunkHandler('DATE', CH_TABLE
) {}
119 void Save() const override
121 SlTableHeader(_date_desc
);
124 SlGlobList(_date_desc
);
127 void LoadCommon(const SaveLoadTable
&slt
, const SaveLoadCompatTable
&slct
) const
129 const std::vector
<SaveLoad
> oslt
= SlCompatTableHeader(slt
, slct
);
131 if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY
) && SlIterateArray() == -1) return;
133 if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY
) && SlIterateArray() != -1) SlErrorCorrupt("Too many DATE entries");
136 void Load() const override
138 this->LoadCommon(_date_desc
, _date_sl_compat
);
142 void LoadCheck(size_t) const override
144 this->LoadCommon(_date_check_desc
, _date_check_sl_compat
);
146 if (IsSavegameVersionBefore(SLV_31
)) {
147 _load_check_data
.current_date
+= CalendarTime::DAYS_TILL_ORIGINAL_BASE_YEAR
;
152 static const SaveLoad _view_desc
[] = {
153 SLEG_CONDVAR("x", _saved_scrollpos_x
, SLE_FILE_I16
| SLE_VAR_I32
, SL_MIN_VERSION
, SLV_6
),
154 SLEG_CONDVAR("x", _saved_scrollpos_x
, SLE_INT32
, SLV_6
, SL_MAX_VERSION
),
155 SLEG_CONDVAR("y", _saved_scrollpos_y
, SLE_FILE_I16
| SLE_VAR_I32
, SL_MIN_VERSION
, SLV_6
),
156 SLEG_CONDVAR("y", _saved_scrollpos_y
, SLE_INT32
, SLV_6
, SL_MAX_VERSION
),
157 SLEG_VAR("zoom", _saved_scrollpos_zoom
, SLE_UINT8
),
160 struct VIEWChunkHandler
: ChunkHandler
{
161 VIEWChunkHandler() : ChunkHandler('VIEW', CH_TABLE
) {}
163 void Save() const override
165 SlTableHeader(_view_desc
);
168 SlGlobList(_view_desc
);
171 void Load() const override
173 const std::vector
<SaveLoad
> slt
= SlCompatTableHeader(_view_desc
, _view_sl_compat
);
175 if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY
) && SlIterateArray() == -1) return;
177 if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY
) && SlIterateArray() != -1) SlErrorCorrupt("Too many DATE entries");
181 static const DATEChunkHandler DATE
;
182 static const VIEWChunkHandler VIEW
;
183 static const ChunkHandlerRef misc_chunk_handlers
[] = {
188 extern const ChunkHandlerTable
_misc_chunk_handlers(misc_chunk_handlers
);