Add: INR currency (#8136)
[openttd-github.git] / src / story.cpp
blob0d465fde85ab261ca3691936613317e0498c6cc0
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 */
8 /** @file story.cpp Handling of stories. */
10 #include "stdafx.h"
11 #include "story_base.h"
12 #include "core/pool_func.hpp"
13 #include "cmd_helper.h"
14 #include "command_func.h"
15 #include "company_base.h"
16 #include "company_func.h"
17 #include "string_func.h"
18 #include "date_func.h"
19 #include "tile_map.h"
20 #include "goal_type.h"
21 #include "goal_base.h"
22 #include "window_func.h"
23 #include "gui.h"
25 #include "safeguards.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 StoryPageElementPool _story_page_element_pool("StoryPageElement");
34 StoryPagePool _story_page_pool("StoryPage");
35 INSTANTIATE_POOL_METHODS(StoryPageElement)
36 INSTANTIATE_POOL_METHODS(StoryPage)
38 /**
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 element type and page id.
48 static bool VerifyElementContentParameters(StoryPageID page_id, StoryPageElementType type, TileIndex tile, uint32 reference, const char *text)
50 switch (type) {
51 case SPET_TEXT:
52 if (StrEmpty(text)) return false;
53 break;
54 case SPET_LOCATION:
55 if (StrEmpty(text)) return false;
56 if (!IsValidTile(tile)) return false;
57 break;
58 case SPET_GOAL:
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;
62 break;
63 default:
64 return false;
67 return true;
70 /**
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)
80 switch (pe.type) {
81 case SPET_TEXT:
82 pe.text = stredup(text);
83 break;
84 case SPET_LOCATION:
85 pe.text = stredup(text);
86 pe.referenced_id = tile;
87 break;
88 case SPET_GOAL:
89 pe.referenced_id = (GoalID)reference;
90 break;
91 default: NOT_REACHED();
95 /**
96 * Create a new story page.
97 * @param tile unused.
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.
101 * @param p2 unused.
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 (_story_page_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;
122 s->date = _date;
123 s->company = company;
124 if (StrEmpty(text)) {
125 s->title = nullptr;
126 } else {
127 s->title = stredup(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 = (StoryPageID)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 for (StoryPageElement *iter : StoryPageElement::Iterate()) {
161 if (iter->page == page_id) element_count++;
163 if (element_count >= 128) return CMD_ERROR;
165 if (_current_company != OWNER_DEITY) return CMD_ERROR;
166 if (!StoryPage::IsValidID(page_id)) return CMD_ERROR;
167 if (!VerifyElementContentParameters(page_id, type, tile, p2, text)) return CMD_ERROR;
169 if (flags & DC_EXEC) {
170 if (_story_page_element_pool.items == 0) {
171 /* Initialize the next sort value variable. */
172 _story_page_element_next_sort_value = 0;
175 StoryPageElement *pe = new StoryPageElement();
176 pe->sort_value = _story_page_element_next_sort_value;
177 pe->type = type;
178 pe->page = page_id;
179 UpdateElement(*pe, tile, p2, text);
181 InvalidateWindowClassesData(WC_STORY_BOOK, page_id);
183 _new_story_page_element_id = pe->index;
184 _story_page_element_next_sort_value++;
187 return CommandCost();
191 * Update a new story page element.
192 * @param tile Tile location if it is a location page element, otherwise unused.
193 * @param flags type of operation
194 * @param p1 various bitstuffed elements
195 * - p1 = (bit 0 - 15) - The page element to update.
196 * (bit 16 - 31) - unused
197 * @param p2 Id of referenced object
198 * @param text Text content in case it is a text or location page element
199 * @return the cost of this operation or an error
201 CommandCost CmdUpdateStoryPageElement(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
203 StoryPageElementID page_element_id = (StoryPageElementID)GB(p1, 0, 16);
205 if (_current_company != OWNER_DEITY) return CMD_ERROR;
206 if (!StoryPageElement::IsValidID(page_element_id)) return CMD_ERROR;
208 StoryPageElement *pe = StoryPageElement::Get(page_element_id);
209 StoryPageID page_id = pe->page;
210 StoryPageElementType type = pe->type;
212 if (!VerifyElementContentParameters(page_id, type, tile, p2, text)) return CMD_ERROR;
214 if (flags & DC_EXEC) {
215 UpdateElement(*pe, tile, p2, text);
216 InvalidateWindowClassesData(WC_STORY_BOOK, pe->page);
219 return CommandCost();
223 * Update title of a story page.
224 * @param tile unused.
225 * @param flags type of operation
226 * @param p1 = (bit 0 - 15) - StoryPageID to update.
227 * @param p2 unused
228 * @param text title text of the story page.
229 * @return the cost of this operation or an error
231 CommandCost CmdSetStoryPageTitle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
233 if (_current_company != OWNER_DEITY) return CMD_ERROR;
234 StoryPageID page_id = (StoryPageID)GB(p1, 0, 16);
235 if (!StoryPage::IsValidID(page_id)) return CMD_ERROR;
237 if (flags & DC_EXEC) {
238 StoryPage *p = StoryPage::Get(page_id);
239 free(p->title);
240 if (StrEmpty(text)) {
241 p->title = nullptr;
242 } else {
243 p->title = stredup(text);
246 InvalidateWindowClassesData(WC_STORY_BOOK, page_id);
249 return CommandCost();
253 * Update date of a story page.
254 * @param tile unused.
255 * @param flags type of operation
256 * @param p1 = (bit 0 - 15) - StoryPageID to update.
257 * @param p2 = (bit 0 - 31) - date
258 * @param text unused
259 * @return the cost of this operation or an error
261 CommandCost CmdSetStoryPageDate(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
263 if (_current_company != OWNER_DEITY) return CMD_ERROR;
264 StoryPageID page_id = (StoryPageID)GB(p1, 0, 16);
265 if (!StoryPage::IsValidID(page_id)) return CMD_ERROR;
266 Date date = (Date)p2;
268 if (flags & DC_EXEC) {
269 StoryPage *p = StoryPage::Get(page_id);
270 p->date = date;
272 InvalidateWindowClassesData(WC_STORY_BOOK, page_id);
275 return CommandCost();
279 * Display a story page for all clients that are allowed to
280 * view the story page.
281 * @param tile unused.
282 * @param flags type of operation
283 * @param p1 = (bit 0 - 15) - StoryPageID to show.
284 * @param p2 unused
285 * @param text unused
286 * @return the cost of this operation or an error
288 CommandCost CmdShowStoryPage(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
290 if (_current_company != OWNER_DEITY) return CMD_ERROR;
291 StoryPageID page_id = (StoryPageID)GB(p1, 0, 16);
292 if (!StoryPage::IsValidID(page_id)) return CMD_ERROR;
294 if (flags & DC_EXEC) {
295 StoryPage *g = StoryPage::Get(page_id);
296 if ((g->company != INVALID_COMPANY && g->company == _local_company) || (g->company == INVALID_COMPANY && Company::IsValidID(_local_company))) ShowStoryBook(_local_company, page_id);
299 return CommandCost();
302 * Remove a story page and associated story page elements.
303 * @param tile unused.
304 * @param flags type of operation
305 * @param p1 = (bit 0 - 15) - StoryPageID to remove.
306 * @param p2 unused.
307 * @param text unused.
308 * @return the cost of this operation or an error
310 CommandCost CmdRemoveStoryPage(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
312 if (_current_company != OWNER_DEITY) return CMD_ERROR;
313 StoryPageID page_id = (StoryPageID)p1;
314 if (!StoryPage::IsValidID(page_id)) return CMD_ERROR;
316 if (flags & DC_EXEC) {
317 StoryPage *p = StoryPage::Get(page_id);
319 for (StoryPageElement *pe : StoryPageElement::Iterate()) {
320 if (pe->page == p->index) {
321 delete pe;
325 delete p;
327 InvalidateWindowClassesData(WC_STORY_BOOK, -1);
328 if (StoryPage::GetNumItems() == 0) InvalidateWindowData(WC_MAIN_TOOLBAR, 0);
331 return CommandCost();
335 * Remove a story page element
336 * @param tile unused.
337 * @param flags type of operation
338 * @param p1 = (bit 0 - 15) - StoryPageElementID to remove.
339 * @param p2 unused.
340 * @param text unused.
341 * @return the cost of this operation or an error
343 CommandCost CmdRemoveStoryPageElement(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
345 if (_current_company != OWNER_DEITY) return CMD_ERROR;
346 StoryPageElementID page_element_id = (StoryPageElementID)p1;
347 if (!StoryPageElement::IsValidID(page_element_id)) return CMD_ERROR;
349 if (flags & DC_EXEC) {
350 StoryPageElement *pe = StoryPageElement::Get(page_element_id);
351 StoryPageID page_id = pe->page;
353 delete pe;
355 InvalidateWindowClassesData(WC_STORY_BOOK, page_id);
358 return CommandCost();