1 /*
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/>.
6  */
7 
8 /** @file story_sl.cpp Code handling saving and loading of story pages */
9 
10 #include "../stdafx.h"
11 
12 #include "saveload.h"
13 #include "compat/story_sl_compat.h"
14 
15 #include "../story_base.h"
16 
17 #include "../safeguards.h"
18 
19 /** Called after load to trash broken pages. */
AfterLoadStoryBook()20 void AfterLoadStoryBook()
21 {
22 	if (IsSavegameVersionBefore(SLV_185)) {
23 		/* Trash all story pages and page elements because
24 		 * they were saved with wrong data types.
25 		 */
26 		_story_page_element_pool.CleanPool();
27 		_story_page_pool.CleanPool();
28 	}
29 }
30 
31 static const SaveLoad _story_page_elements_desc[] = {
32 	SLE_CONDVAR(StoryPageElement, sort_value,    SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION,   SLV_185),
33 	SLE_CONDVAR(StoryPageElement, sort_value,    SLE_UINT32,                 SLV_185, SL_MAX_VERSION),
34 	    SLE_VAR(StoryPageElement, page,          SLE_UINT16),
35 	SLE_CONDVAR(StoryPageElement, type,          SLE_FILE_U16 | SLE_VAR_U8,  SL_MIN_VERSION,   SLV_185),
36 	SLE_CONDVAR(StoryPageElement, type,          SLE_UINT8,                  SLV_185, SL_MAX_VERSION),
37 	    SLE_VAR(StoryPageElement, referenced_id, SLE_UINT32),
38 	    SLE_STR(StoryPageElement, text,          SLE_STR | SLF_ALLOW_CONTROL, 0),
39 };
40 
41 struct STPEChunkHandler : ChunkHandler {
STPEChunkHandlerSTPEChunkHandler42 	STPEChunkHandler() : ChunkHandler('STPE', CH_TABLE) {}
43 
SaveSTPEChunkHandler44 	void Save() const override
45 	{
46 		SlTableHeader(_story_page_elements_desc);
47 
48 		for (StoryPageElement *s : StoryPageElement::Iterate()) {
49 			SlSetArrayIndex(s->index);
50 			SlObject(s, _story_page_elements_desc);
51 		}
52 	}
53 
LoadSTPEChunkHandler54 	void Load() const override
55 	{
56 		const std::vector<SaveLoad> slt = SlCompatTableHeader(_story_page_elements_desc, _story_page_elements_sl_compat);
57 
58 		int index;
59 		uint32 max_sort_value = 0;
60 		while ((index = SlIterateArray()) != -1) {
61 			StoryPageElement *s = new (index) StoryPageElement();
62 			SlObject(s, slt);
63 			if (s->sort_value > max_sort_value) {
64 				max_sort_value = s->sort_value;
65 			}
66 		}
67 		/* Update the next sort value, so that the next
68 		 * created page is shown after all existing pages.
69 		 */
70 		_story_page_element_next_sort_value = max_sort_value + 1;
71 	}
72 };
73 
74 static const SaveLoad _story_pages_desc[] = {
75 	SLE_CONDVAR(StoryPage, sort_value, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION,   SLV_185),
76 	SLE_CONDVAR(StoryPage, sort_value, SLE_UINT32,                 SLV_185, SL_MAX_VERSION),
77 	    SLE_VAR(StoryPage, date,       SLE_UINT32),
78 	SLE_CONDVAR(StoryPage, company,    SLE_FILE_U16 | SLE_VAR_U8,  SL_MIN_VERSION,   SLV_185),
79 	SLE_CONDVAR(StoryPage, company,    SLE_UINT8,                  SLV_185, SL_MAX_VERSION),
80 	    SLE_STR(StoryPage, title,      SLE_STR | SLF_ALLOW_CONTROL, 0),
81 };
82 
83 struct STPAChunkHandler : ChunkHandler {
STPAChunkHandlerSTPAChunkHandler84 	STPAChunkHandler() : ChunkHandler('STPA', CH_TABLE) {}
85 
SaveSTPAChunkHandler86 	void Save() const override
87 	{
88 		SlTableHeader(_story_pages_desc);
89 
90 		for (StoryPage *s : StoryPage::Iterate()) {
91 			SlSetArrayIndex(s->index);
92 			SlObject(s, _story_pages_desc);
93 		}
94 	}
95 
LoadSTPAChunkHandler96 	void Load() const override
97 	{
98 		const std::vector<SaveLoad> slt = SlCompatTableHeader(_story_pages_desc, _story_pages_sl_compat);
99 
100 		int index;
101 		uint32 max_sort_value = 0;
102 		while ((index = SlIterateArray()) != -1) {
103 			StoryPage *s = new (index) StoryPage();
104 			SlObject(s, slt);
105 			if (s->sort_value > max_sort_value) {
106 				max_sort_value = s->sort_value;
107 			}
108 		}
109 		/* Update the next sort value, so that the next
110 		 * created page is shown after all existing pages.
111 		 */
112 		_story_page_next_sort_value = max_sort_value + 1;
113 	}
114 };
115 
116 static const STPEChunkHandler STPE;
117 static const STPAChunkHandler STPA;
118 static const ChunkHandlerRef story_page_chunk_handlers[] = {
119 	STPE,
120 	STPA,
121 };
122 
123 extern const ChunkHandlerTable _story_page_chunk_handlers(story_page_chunk_handlers);
124