4 * This file is part of OpenTTD.
5 * 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.
6 * 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.
7 * 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/>.
10 /** @file story.cpp Handling of stories. */
13 #include "story_base.h"
14 #include "core/pool_func.hpp"
15 #include "cmd_helper.h"
16 #include "command_func.h"
17 #include "company_base.h"
18 #include "company_func.h"
20 #include "date_func.h"
21 #include "map/class.h"
22 #include "goal_type.h"
23 #include "goal_base.h"
24 #include "window_func.h"
28 StoryPageElementID _new_story_page_element_id
;
29 StoryPageID _new_story_page_id
;
30 uint32 _story_page_element_next_sort_value
;
31 uint32 _story_page_next_sort_value
;
33 template<> StoryPageElement::Pool
StoryPageElement::PoolItem::pool ("StoryPageElement");
34 INSTANTIATE_POOL_METHODS(StoryPageElement
)
35 template<> StoryPage::Pool
StoryPage::PoolItem::pool ("StoryPage");;
36 INSTANTIATE_POOL_METHODS(StoryPage
)
39 * This helper for Create/Update PageElement Cmd procedure verifies if the page
40 * element parameters are correct for the given page element type.
41 * @param page_id The page id of the page which the page element (will) belong to
42 * @param type The type of the page element to create/update
43 * @param tile The tile parameter of the DoCommand proc
44 * @param reference The reference parameter of the DoCommand proc (p2)
45 * @param text The text parameter of the DoCommand proc
46 * @return true, if and only if the given parameters are valid for the given page elment type and page id.
48 static bool VerifyElementContentParameters(StoryPageID page_id
, StoryPageElementType type
, TileIndex tile
, uint32 reference
, const char *text
)
52 if (StrEmpty(text
)) return false;
55 if (StrEmpty(text
)) return false;
56 if (!IsValidTile(tile
)) return false;
59 if (!Goal::IsValidID((GoalID
)reference
)) return false;
60 /* Reject company specific goals on global pages */
61 if (StoryPage::Get(page_id
)->company
== INVALID_COMPANY
&& Goal::Get((GoalID
)reference
)->company
!= INVALID_COMPANY
) return false;
71 * This helper for Create/Update PageElement Cmd procedure updates a page
72 * element with new content data.
73 * @param pe The page element to update
74 * @param tile The tile parameter of the DoCommand proc
75 * @param reference The reference parameter of the DoCommand proc (p2)
76 * @param text The text parameter of the DoCommand proc
78 static void UpdateElement(StoryPageElement
&pe
, TileIndex tile
, uint32 reference
, const char *text
)
82 pe
.text
= xstrdup(text
);
85 pe
.text
= xstrdup(text
);
86 pe
.referenced_id
= tile
;
89 pe
.referenced_id
= (GoalID
)reference
;
91 default: NOT_REACHED();
96 * Create a new story page.
98 * @param flags type of operation
99 * @param p1 various bitstuffed elements
100 * - p1 = (bit 0 - 7) - Company for which this story page belongs to.
102 * @param text Title of the story page. Null is allowed in which case a generic page title is provided by OpenTTD.
103 * @return the cost of this operation or an error
105 CommandCost
CmdCreateStoryPage(TileIndex tile
, DoCommandFlag flags
, uint32 p1
, uint32 p2
, const char *text
)
107 if (!StoryPage::CanAllocateItem()) return CMD_ERROR
;
109 CompanyID company
= (CompanyID
)GB(p1
, 0, 8);
111 if (_current_company
!= OWNER_DEITY
) return CMD_ERROR
;
112 if (company
!= INVALID_COMPANY
&& !Company::IsValidID(company
)) return CMD_ERROR
;
114 if (flags
& DC_EXEC
) {
115 if (StoryPage::pool
.items
== 0) {
116 /* Initialize the next sort value variable. */
117 _story_page_next_sort_value
= 0;
120 StoryPage
*s
= new StoryPage();
121 s
->sort_value
= _story_page_next_sort_value
;
123 s
->company
= company
;
124 if (StrEmpty(text
)) {
127 s
->title
= xstrdup(text
);
130 InvalidateWindowClassesData(WC_STORY_BOOK
, -1);
131 if (StoryPage::GetNumItems() == 1) InvalidateWindowData(WC_MAIN_TOOLBAR
, 0);
133 _new_story_page_id
= s
->index
;
134 _story_page_next_sort_value
++;
137 return CommandCost();
141 * Create a new story page element.
142 * @param tile Tile location if it is a location page element, otherwise unused.
143 * @param flags type of operation
144 * @param p1 various bitstuffed elements
145 * - p1 = (bit 0 - 15) - The page which the element belongs to.
146 * (bit 16 - 23) - Page element type
147 * @param p2 Id of referenced object
148 * @param text Text content in case it is a text or location page element
149 * @return the cost of this operation or an error
151 CommandCost
CmdCreateStoryPageElement(TileIndex tile
, DoCommandFlag flags
, uint32 p1
, uint32 p2
, const char *text
)
153 if (!StoryPageElement::CanAllocateItem()) return CMD_ERROR
;
155 StoryPageID page_id
= (CompanyID
)GB(p1
, 0, 16);
156 StoryPageElementType type
= Extract
<StoryPageElementType
, 16, 8>(p1
);
158 /* Allow at most 128 elements per page. */
159 uint16 element_count
= 0;
160 StoryPageElement
*iter
;
161 FOR_ALL_STORY_PAGE_ELEMENTS(iter
) {
162 if (iter
->page
== page_id
) element_count
++;
164 if (element_count
>= 128) return CMD_ERROR
;
166 if (_current_company
!= OWNER_DEITY
) return CMD_ERROR
;
167 if (!StoryPage::IsValidID(page_id
)) return CMD_ERROR
;
168 if (!VerifyElementContentParameters(page_id
, type
, tile
, p2
, text
)) return CMD_ERROR
;
170 if (flags
& DC_EXEC
) {
171 if (StoryPageElement::pool
.items
== 0) {
172 /* Initialize the next sort value variable. */
173 _story_page_element_next_sort_value
= 0;
176 StoryPageElement
*pe
= new StoryPageElement();
177 pe
->sort_value
= _story_page_element_next_sort_value
;
180 UpdateElement(*pe
, tile
, p2
, text
);
182 InvalidateWindowClassesData(WC_STORY_BOOK
, page_id
);
184 _new_story_page_element_id
= pe
->index
;
185 _story_page_element_next_sort_value
++;
188 return CommandCost();
192 * Update a new story page element.
193 * @param tile Tile location if it is a location page element, otherwise unused.
194 * @param flags type of operation
195 * @param p1 various bitstuffed elements
196 * - p1 = (bit 0 - 15) - The page element to update.
197 * (bit 16 - 31) - unused
198 * @param p2 Id of referenced object
199 * @param text Text content in case it is a text or location page element
200 * @return the cost of this operation or an error
202 CommandCost
CmdUpdateStoryPageElement(TileIndex tile
, DoCommandFlag flags
, uint32 p1
, uint32 p2
, const char *text
)
204 StoryPageElementID page_element_id
= (StoryPageElementID
)GB(p1
, 0, 16);
206 if (_current_company
!= OWNER_DEITY
) return CMD_ERROR
;
207 if (!StoryPageElement::IsValidID(page_element_id
)) return CMD_ERROR
;
209 StoryPageElement
*pe
= StoryPageElement::Get(page_element_id
);
210 StoryPageID page_id
= pe
->page
;
211 StoryPageElementType type
= pe
->type
;
213 if (!VerifyElementContentParameters(page_id
, type
, tile
, p2
, text
)) return CMD_ERROR
;
215 if (flags
& DC_EXEC
) {
216 UpdateElement(*pe
, tile
, p2
, text
);
217 InvalidateWindowClassesData(WC_STORY_BOOK
, pe
->page
);
220 return CommandCost();
224 * Update title of a story page.
225 * @param tile unused.
226 * @param flags type of operation
227 * @param p1 = (bit 0 - 15) - StoryPageID to update.
229 * @param text title text of the story page.
230 * @return the cost of this operation or an error
232 CommandCost
CmdSetStoryPageTitle(TileIndex tile
, DoCommandFlag flags
, uint32 p1
, uint32 p2
, const char *text
)
234 if (_current_company
!= OWNER_DEITY
) return CMD_ERROR
;
235 StoryPageID page_id
= (StoryPageID
)GB(p1
, 0, 16);
236 if (!StoryPage::IsValidID(page_id
)) return CMD_ERROR
;
238 if (flags
& DC_EXEC
) {
239 StoryPage
*p
= StoryPage::Get(page_id
);
241 if (StrEmpty(text
)) {
244 p
->title
= xstrdup(text
);
247 InvalidateWindowClassesData(WC_STORY_BOOK
, page_id
);
250 return CommandCost();
254 * Update date of a story page.
255 * @param tile unused.
256 * @param flags type of operation
257 * @param p1 = (bit 0 - 15) - StoryPageID to update.
258 * @param p2 = (bit 0 - 31) - date
260 * @return the cost of this operation or an error
262 CommandCost
CmdSetStoryPageDate(TileIndex tile
, DoCommandFlag flags
, uint32 p1
, uint32 p2
, const char *text
)
264 if (_current_company
!= OWNER_DEITY
) return CMD_ERROR
;
265 StoryPageID page_id
= (StoryPageID
)GB(p1
, 0, 16);
266 if (!StoryPage::IsValidID(page_id
)) return CMD_ERROR
;
267 Date date
= (Date
)p2
;
269 if (flags
& DC_EXEC
) {
270 StoryPage
*p
= StoryPage::Get(page_id
);
273 InvalidateWindowClassesData(WC_STORY_BOOK
, page_id
);
276 return CommandCost();
280 * Display a story page for all clients that are allowed to
281 * view the story page.
282 * @param tile unused.
283 * @param flags type of operation
284 * @param p1 = (bit 0 - 15) - StoryPageID to show.
287 * @return the cost of this operation or an error
289 CommandCost
CmdShowStoryPage(TileIndex tile
, DoCommandFlag flags
, uint32 p1
, uint32 p2
, const char *text
)
291 if (_current_company
!= OWNER_DEITY
) return CMD_ERROR
;
292 StoryPageID page_id
= (StoryPageID
)GB(p1
, 0, 16);
293 if (!StoryPage::IsValidID(page_id
)) return CMD_ERROR
;
295 if (flags
& DC_EXEC
) {
296 StoryPage
*g
= StoryPage::Get(page_id
);
297 if ((g
->company
!= INVALID_COMPANY
&& g
->company
== _local_company
) || (g
->company
== INVALID_COMPANY
&& Company::IsValidID(_local_company
))) ShowStoryBook(_local_company
, page_id
);
300 return CommandCost();
303 * Remove a story page and associated story page elements.
304 * @param tile unused.
305 * @param flags type of operation
306 * @param p1 = (bit 0 - 15) - StoryPageID to remove.
308 * @param text unused.
309 * @return the cost of this operation or an error
311 CommandCost
CmdRemoveStoryPage(TileIndex tile
, DoCommandFlag flags
, uint32 p1
, uint32 p2
, const char *text
)
313 if (_current_company
!= OWNER_DEITY
) return CMD_ERROR
;
314 StoryPageID page_id
= (StoryPageID
)p1
;
315 if (!StoryPage::IsValidID(page_id
)) return CMD_ERROR
;
317 if (flags
& DC_EXEC
) {
318 StoryPage
*p
= StoryPage::Get(page_id
);
320 StoryPageElement
*pe
;
321 FOR_ALL_STORY_PAGE_ELEMENTS(pe
) {
322 if (pe
->page
== p
->index
) {
329 InvalidateWindowClassesData(WC_STORY_BOOK
, -1);
330 if (StoryPage::GetNumItems() == 0) InvalidateWindowData(WC_MAIN_TOOLBAR
, 0);
333 return CommandCost();
337 * Remove a story page element
338 * @param tile unused.
339 * @param flags type of operation
340 * @param p1 = (bit 0 - 15) - StoryPageElementID to remove.
342 * @param text unused.
343 * @return the cost of this operation or an error
345 CommandCost
CmdRemoveStoryPageElement(TileIndex tile
, DoCommandFlag flags
, uint32 p1
, uint32 p2
, const char *text
)
347 if (_current_company
!= OWNER_DEITY
) return CMD_ERROR
;
348 StoryPageElementID page_element_id
= (StoryPageElementID
)p1
;
349 if (!StoryPageElement::IsValidID(page_element_id
)) return CMD_ERROR
;
351 if (flags
& DC_EXEC
) {
352 StoryPageElement
*pe
= StoryPageElement::Get(page_element_id
);
353 StoryPageID page_id
= pe
->page
;
357 InvalidateWindowClassesData(WC_STORY_BOOK
, page_id
);
360 return CommandCost();