Update readme and changelog for v1.26.0
[openttd-joker.git] / src / story.cpp
blobd8a35a964281b4bd463cbdc4e570b697750fd7cd
1 /* $Id: story.cpp 26306 2014-02-06 19:48:19Z zuu $ */
3 /*
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/>.
8 */
10 /** @file story.cpp Handling of stories. */
12 #include "stdafx.h"
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"
19 #include "string_func.h"
20 #include "date_func.h"
21 #include "tile_map.h"
22 #include "goal_type.h"
23 #include "goal_base.h"
24 #include "window_func.h"
25 #include "gui.h"
27 #include "safeguards.h"
30 StoryPageElementID _new_story_page_element_id;
31 StoryPageID _new_story_page_id;
32 uint32 _story_page_element_next_sort_value;
33 uint32 _story_page_next_sort_value;
35 StoryPageElementPool _story_page_element_pool("StoryPageElement");
36 StoryPagePool _story_page_pool("StoryPage");
37 INSTANTIATE_POOL_METHODS(StoryPageElement)
38 INSTANTIATE_POOL_METHODS(StoryPage)
40 /**
41 * This helper for Create/Update PageElement Cmd procedure verifies if the page
42 * element parameters are correct for the given page element type.
43 * @param page_id The page id of the page which the page element (will) belong to
44 * @param type The type of the page element to create/update
45 * @param tile The tile parameter of the DoCommand proc
46 * @param reference The reference parameter of the DoCommand proc (p2)
47 * @param text The text parameter of the DoCommand proc
48 * @return true, if and only if the given parameters are valid for the given page elment type and page id.
50 static bool VerifyElementContentParameters(StoryPageID page_id, StoryPageElementType type, TileIndex tile, uint32 reference, const char *text)
52 switch (type) {
53 case SPET_TEXT:
54 if (StrEmpty(text)) return false;
55 break;
56 case SPET_LOCATION:
57 if (StrEmpty(text)) return false;
58 if (!IsValidTile(tile)) return false;
59 break;
60 case SPET_GOAL:
61 if (!Goal::IsValidID((GoalID)reference)) return false;
62 /* Reject company specific goals on global pages */
63 if (StoryPage::Get(page_id)->company == INVALID_COMPANY && Goal::Get((GoalID)reference)->company != INVALID_COMPANY) return false;
64 break;
65 default:
66 return false;
69 return true;
72 /**
73 * This helper for Create/Update PageElement Cmd procedure updates a page
74 * element with new content data.
75 * @param pe The page element to update
76 * @param tile The tile parameter of the DoCommand proc
77 * @param reference The reference parameter of the DoCommand proc (p2)
78 * @param text The text parameter of the DoCommand proc
80 static void UpdateElement(StoryPageElement &pe, TileIndex tile, uint32 reference, const char *text)
82 switch (pe.type) {
83 case SPET_TEXT:
84 pe.text = stredup(text);
85 break;
86 case SPET_LOCATION:
87 pe.text = stredup(text);
88 pe.referenced_id = tile;
89 break;
90 case SPET_GOAL:
91 pe.referenced_id = (GoalID)reference;
92 break;
93 default: NOT_REACHED();
97 /**
98 * Create a new story page.
99 * @param tile unused.
100 * @param flags type of operation
101 * @param p1 various bitstuffed elements
102 * - p1 = (bit 0 - 7) - Company for which this story page belongs to.
103 * @param p2 unused.
104 * @param text Title of the story page. Null is allowed in which case a generic page title is provided by OpenTTD.
105 * @return the cost of this operation or an error
107 CommandCost CmdCreateStoryPage(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
109 if (!StoryPage::CanAllocateItem()) return CommandError();
111 CompanyID company = (CompanyID)GB(p1, 0, 8);
113 if (_current_company != OWNER_DEITY) return CommandError();
114 if (company != INVALID_COMPANY && !Company::IsValidID(company)) return CommandError();
116 if (flags & DC_EXEC) {
117 if (_story_page_pool.items == 0) {
118 /* Initialize the next sort value variable. */
119 _story_page_next_sort_value = 0;
122 StoryPage *s = new StoryPage();
123 s->sort_value = _story_page_next_sort_value;
124 s->date = _date;
125 s->company = company;
126 if (StrEmpty(text)) {
127 s->title = nullptr;
128 } else {
129 s->title = stredup(text);
132 InvalidateWindowClassesData(WC_STORY_BOOK, -1);
133 if (StoryPage::GetNumItems() == 1) InvalidateWindowData(WC_MAIN_TOOLBAR, 0);
135 _new_story_page_id = s->index;
136 _story_page_next_sort_value++;
139 return CommandCost();
143 * Create a new story page element.
144 * @param tile Tile location if it is a location page element, otherwise unused.
145 * @param flags type of operation
146 * @param p1 various bitstuffed elements
147 * - p1 = (bit 0 - 15) - The page which the element belongs to.
148 * (bit 16 - 23) - Page element type
149 * @param p2 Id of referenced object
150 * @param text Text content in case it is a text or location page element
151 * @return the cost of this operation or an error
153 CommandCost CmdCreateStoryPageElement(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
155 if (!StoryPageElement::CanAllocateItem()) return CommandError();
157 StoryPageID page_id = (CompanyID)GB(p1, 0, 16);
158 StoryPageElementType type = Extract<StoryPageElementType, 16, 8>(p1);
160 /* Allow at most 128 elements per page. */
161 uint16 element_count = 0;
162 StoryPageElement *iter;
163 FOR_ALL_STORY_PAGE_ELEMENTS(iter) {
164 if (iter->page == page_id) element_count++;
166 if (element_count >= 128) return CommandError();
168 if (_current_company != OWNER_DEITY) return CommandError();
169 if (!StoryPage::IsValidID(page_id)) return CommandError();
170 if (!VerifyElementContentParameters(page_id, type, tile, p2, text)) return CommandError();
172 if (flags & DC_EXEC) {
173 if (_story_page_element_pool.items == 0) {
174 /* Initialize the next sort value variable. */
175 _story_page_element_next_sort_value = 0;
178 StoryPageElement *pe = new StoryPageElement();
179 pe->sort_value = _story_page_element_next_sort_value;
180 pe->type = type;
181 pe->page = page_id;
182 UpdateElement(*pe, tile, p2, text);
184 InvalidateWindowClassesData(WC_STORY_BOOK, page_id);
186 _new_story_page_element_id = pe->index;
187 _story_page_element_next_sort_value++;
190 return CommandCost();
194 * Update a new story page element.
195 * @param tile Tile location if it is a location page element, otherwise unused.
196 * @param flags type of operation
197 * @param p1 various bitstuffed elements
198 * - p1 = (bit 0 - 15) - The page element to update.
199 * (bit 16 - 31) - unused
200 * @param p2 Id of referenced object
201 * @param text Text content in case it is a text or location page element
202 * @return the cost of this operation or an error
204 CommandCost CmdUpdateStoryPageElement(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
206 StoryPageElementID page_element_id = (StoryPageElementID)GB(p1, 0, 16);
208 if (_current_company != OWNER_DEITY) return CommandError();
209 if (!StoryPageElement::IsValidID(page_element_id)) return CommandError();
211 StoryPageElement *pe = StoryPageElement::Get(page_element_id);
212 StoryPageID page_id = pe->page;
213 StoryPageElementType type = pe->type;
215 if (!VerifyElementContentParameters(page_id, type, tile, p2, text)) return CommandError();
217 if (flags & DC_EXEC) {
218 UpdateElement(*pe, tile, p2, text);
219 InvalidateWindowClassesData(WC_STORY_BOOK, pe->page);
222 return CommandCost();
226 * Update title of a story page.
227 * @param tile unused.
228 * @param flags type of operation
229 * @param p1 = (bit 0 - 15) - StoryPageID to update.
230 * @param p2 unused
231 * @param text title text of the story page.
232 * @return the cost of this operation or an error
234 CommandCost CmdSetStoryPageTitle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
236 if (_current_company != OWNER_DEITY) return CommandError();
237 StoryPageID page_id = (StoryPageID)GB(p1, 0, 16);
238 if (!StoryPage::IsValidID(page_id)) return CommandError();
240 if (flags & DC_EXEC) {
241 StoryPage *p = StoryPage::Get(page_id);
242 free(p->title);
243 if (StrEmpty(text)) {
244 p->title = nullptr;
245 } else {
246 p->title = stredup(text);
249 InvalidateWindowClassesData(WC_STORY_BOOK, page_id);
252 return CommandCost();
256 * Update date of a story page.
257 * @param tile unused.
258 * @param flags type of operation
259 * @param p1 = (bit 0 - 15) - StoryPageID to update.
260 * @param p2 = (bit 0 - 31) - date
261 * @param text unused
262 * @return the cost of this operation or an error
264 CommandCost CmdSetStoryPageDate(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
266 if (_current_company != OWNER_DEITY) return CommandError();
267 StoryPageID page_id = (StoryPageID)GB(p1, 0, 16);
268 if (!StoryPage::IsValidID(page_id)) return CommandError();
269 Date date = (Date)p2;
271 if (flags & DC_EXEC) {
272 StoryPage *p = StoryPage::Get(page_id);
273 p->date = date;
275 InvalidateWindowClassesData(WC_STORY_BOOK, page_id);
278 return CommandCost();
282 * Display a story page for all clients that are allowed to
283 * view the story page.
284 * @param tile unused.
285 * @param flags type of operation
286 * @param p1 = (bit 0 - 15) - StoryPageID to show.
287 * @param p2 unused
288 * @param text unused
289 * @return the cost of this operation or an error
291 CommandCost CmdShowStoryPage(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
293 if (_current_company != OWNER_DEITY) return CommandError();
294 StoryPageID page_id = (StoryPageID)GB(p1, 0, 16);
295 if (!StoryPage::IsValidID(page_id)) return CommandError();
297 if (flags & DC_EXEC) {
298 StoryPage *g = StoryPage::Get(page_id);
299 if ((g->company != INVALID_COMPANY && g->company == _local_company) || (g->company == INVALID_COMPANY && Company::IsValidID(_local_company))) ShowStoryBook(_local_company, page_id);
302 return CommandCost();
305 * Remove a story page and associated story page elements.
306 * @param tile unused.
307 * @param flags type of operation
308 * @param p1 = (bit 0 - 15) - StoryPageID to remove.
309 * @param p2 unused.
310 * @param text unused.
311 * @return the cost of this operation or an error
313 CommandCost CmdRemoveStoryPage(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
315 if (_current_company != OWNER_DEITY) return CommandError();
316 StoryPageID page_id = (StoryPageID)p1;
317 if (!StoryPage::IsValidID(page_id)) return CommandError();
319 if (flags & DC_EXEC) {
320 StoryPage *p = StoryPage::Get(page_id);
322 StoryPageElement *pe;
323 FOR_ALL_STORY_PAGE_ELEMENTS(pe) {
324 if (pe->page == p->index) {
325 delete pe;
329 delete p;
331 InvalidateWindowClassesData(WC_STORY_BOOK, -1);
332 if (StoryPage::GetNumItems() == 0) InvalidateWindowData(WC_MAIN_TOOLBAR, 0);
335 return CommandCost();
339 * Remove a story page element
340 * @param tile unused.
341 * @param flags type of operation
342 * @param p1 = (bit 0 - 15) - StoryPageElementID to remove.
343 * @param p2 unused.
344 * @param text unused.
345 * @return the cost of this operation or an error
347 CommandCost CmdRemoveStoryPageElement(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
349 if (_current_company != OWNER_DEITY) return CommandError();
350 StoryPageElementID page_element_id = (StoryPageElementID)p1;
351 if (!StoryPageElement::IsValidID(page_element_id)) return CommandError();
353 if (flags & DC_EXEC) {
354 StoryPageElement *pe = StoryPageElement::Get(page_element_id);
355 StoryPageID page_id = pe->page;
357 delete pe;
359 InvalidateWindowClassesData(WC_STORY_BOOK, page_id);
362 return CommandCost();