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 script_story_page.hpp Everything to manipulate a story page. */
9 
10 #ifndef SCRIPT_STORY_HPP
11 #define SCRIPT_STORY_HPP
12 
13 #include "script_company.hpp"
14 #include "script_date.hpp"
15 #include "script_vehicle.hpp"
16 #include "../../story_type.h"
17 #include "../../story_base.h"
18 
19 /**
20  * Class that handles story page related functions.
21  *
22  * To create a page:
23  * 1. Create the page
24  * 2. Create page elements that will be appended to the page in the order which they are created.
25  *
26  * Pages can be either global or company specific. It is possible to mix, but the only mixed solution
27  * that will work is to have all global pages first. Once you create the first company specific page,
28  * it is not recommended to add additional global pages unless you clear up all pages first.
29  *
30  * Page elements are stacked vertically on a page. If goal elements are used, the element will
31  * become empty if the goal is removed while the page still exist. Instead of removing the goal,
32  * you can mark it as complete and the Story Book will show that the goal is completed.
33  *
34  * Mind that users might want to go back to old pages later on. Thus do not remove pages in
35  * the story book unless you really need to.
36  *
37  * @api game
38  */
39 class ScriptStoryPage : public ScriptObject {
40 public:
41 	/**
42 	 * The story page IDs.
43 	 */
44 	enum StoryPageID {
45 		/* Note: these values represent part of the in-game StoryPageID enum */
46 		STORY_PAGE_INVALID = ::INVALID_STORY_PAGE, ///< An invalid story page id.
47 	};
48 
49 	/**
50 	 * The story page element IDs.
51 	 */
52 	enum StoryPageElementID {
53 		/* Note: these values represent part of the in-game StoryPageElementID enum */
54 		STORY_PAGE_ELEMENT_INVALID = ::INVALID_STORY_PAGE_ELEMENT, ///< An invalid story page element id.
55 	};
56 
57 	/**
58 	 * Story page element types.
59 	 */
60 	enum StoryPageElementType : byte {
61 		SPET_TEXT = ::SPET_TEXT,                     ///< An element that displays a block of text.
62 		SPET_LOCATION = ::SPET_LOCATION,             ///< An element that displays a single line of text along with a button to view the referenced location.
63 		SPET_GOAL = ::SPET_GOAL,                     ///< An element that displays a goal.
64 		SPET_BUTTON_PUSH = ::SPET_BUTTON_PUSH,       ///< A push button that triggers an immediate event.
65 		SPET_BUTTON_TILE = ::SPET_BUTTON_TILE,       ///< A button that allows the player to select a tile, and triggers an event with the tile.
66 		SPET_BUTTON_VEHICLE = ::SPET_BUTTON_VEHICLE, ///< A button that allows the player to select a vehicle, and triggers an event wih the vehicle.
67 	};
68 
69 	/**
70 	 * Formatting data for button page elements.
71 	 */
72 	typedef uint32 StoryPageButtonFormatting;
73 
74 	/**
75 	 * Formatting and layout flags for story page buttons.
76 	 * The SPBF_FLOAT_LEFT and SPBF_FLOAT_RIGHT flags can not be combined.
77 	 */
78 	enum StoryPageButtonFlags : byte {
79 		SPBF_NONE        = ::SPBF_NONE,        ///< No special formatting for button.
80 		SPBF_FLOAT_LEFT  = ::SPBF_FLOAT_LEFT,  ///< Button is placed to the left of the following paragraph.
81 		SPBF_FLOAT_RIGHT = ::SPBF_FLOAT_RIGHT, ///< Button is placed to the right of the following paragraph.
82 	};
83 
84 	/**
85 	 * Mouse cursors usable by story page buttons.
86 	 */
87 	enum StoryPageButtonCursor : byte {
88 		SPBC_MOUSE          = ::SPBC_MOUSE,
89 		SPBC_ZZZ            = ::SPBC_ZZZ,
90 		SPBC_BUOY           = ::SPBC_BUOY,
91 		SPBC_QUERY          = ::SPBC_QUERY,
92 		SPBC_HQ             = ::SPBC_HQ,
93 		SPBC_SHIP_DEPOT     = ::SPBC_SHIP_DEPOT,
94 		SPBC_SIGN           = ::SPBC_SIGN,
95 		SPBC_TREE           = ::SPBC_TREE,
96 		SPBC_BUY_LAND       = ::SPBC_BUY_LAND,
97 		SPBC_LEVEL_LAND     = ::SPBC_LEVEL_LAND,
98 		SPBC_TOWN           = ::SPBC_TOWN,
99 		SPBC_INDUSTRY       = ::SPBC_INDUSTRY,
100 		SPBC_ROCKY_AREA     = ::SPBC_ROCKY_AREA,
101 		SPBC_DESERT         = ::SPBC_DESERT,
102 		SPBC_TRANSMITTER    = ::SPBC_TRANSMITTER,
103 		SPBC_AIRPORT        = ::SPBC_AIRPORT,
104 		SPBC_DOCK           = ::SPBC_DOCK,
105 		SPBC_CANAL          = ::SPBC_CANAL,
106 		SPBC_LOCK           = ::SPBC_LOCK,
107 		SPBC_RIVER          = ::SPBC_RIVER,
108 		SPBC_AQUEDUCT       = ::SPBC_AQUEDUCT,
109 		SPBC_BRIDGE         = ::SPBC_BRIDGE,
110 		SPBC_RAIL_STATION   = ::SPBC_RAIL_STATION,
111 		SPBC_TUNNEL_RAIL    = ::SPBC_TUNNEL_RAIL,
112 		SPBC_TUNNEL_ELRAIL  = ::SPBC_TUNNEL_ELRAIL,
113 		SPBC_TUNNEL_MONO    = ::SPBC_TUNNEL_MONO,
114 		SPBC_TUNNEL_MAGLEV  = ::SPBC_TUNNEL_MAGLEV,
115 		SPBC_AUTORAIL       = ::SPBC_AUTORAIL,
116 		SPBC_AUTOELRAIL     = ::SPBC_AUTOELRAIL,
117 		SPBC_AUTOMONO       = ::SPBC_AUTOMONO,
118 		SPBC_AUTOMAGLEV     = ::SPBC_AUTOMAGLEV,
119 		SPBC_WAYPOINT       = ::SPBC_WAYPOINT,
120 		SPBC_RAIL_DEPOT     = ::SPBC_RAIL_DEPOT,
121 		SPBC_ELRAIL_DEPOT   = ::SPBC_ELRAIL_DEPOT,
122 		SPBC_MONO_DEPOT     = ::SPBC_MONO_DEPOT,
123 		SPBC_MAGLEV_DEPOT   = ::SPBC_MAGLEV_DEPOT,
124 		SPBC_CONVERT_RAIL   = ::SPBC_CONVERT_RAIL,
125 		SPBC_CONVERT_ELRAIL = ::SPBC_CONVERT_ELRAIL,
126 		SPBC_CONVERT_MONO   = ::SPBC_CONVERT_MONO,
127 		SPBC_CONVERT_MAGLEV = ::SPBC_CONVERT_MAGLEV,
128 		SPBC_AUTOROAD       = ::SPBC_AUTOROAD,
129 		SPBC_AUTOTRAM       = ::SPBC_AUTOTRAM,
130 		SPBC_ROAD_DEPOT     = ::SPBC_ROAD_DEPOT,
131 		SPBC_BUS_STATION    = ::SPBC_BUS_STATION,
132 		SPBC_TRUCK_STATION  = ::SPBC_TRUCK_STATION,
133 		SPBC_ROAD_TUNNEL    = ::SPBC_ROAD_TUNNEL,
134 		SPBC_CLONE_TRAIN    = ::SPBC_CLONE_TRAIN,
135 		SPBC_CLONE_ROADVEH  = ::SPBC_CLONE_ROADVEH,
136 		SPBC_CLONE_SHIP     = ::SPBC_CLONE_SHIP,
137 		SPBC_CLONE_AIRPLANE = ::SPBC_CLONE_AIRPLANE,
138 		SPBC_DEMOLISH       = ::SPBC_DEMOLISH,
139 		SPBC_LOWERLAND      = ::SPBC_LOWERLAND,
140 		SPBC_RAISELAND      = ::SPBC_RAISELAND,
141 		SPBC_PICKSTATION    = ::SPBC_PICKSTATION,
142 		SPBC_BUILDSIGNALS   = ::SPBC_BUILDSIGNALS,
143 	};
144 
145 	/**
146 	 * Colour codes usable for story page button elements.
147 	 * Place a colour value in the lowest 8 bits of the \c reference parameter to the button.
148 	 */
149 	enum StoryPageButtonColour {
150 		SPBC_DARK_BLUE  = ::COLOUR_DARK_BLUE,
151 		SPBC_PALE_GREEN = ::COLOUR_PALE_GREEN,
152 		SPBC_PINK       = ::COLOUR_PINK,
153 		SPBC_YELLOW     = ::COLOUR_YELLOW,
154 		SPBC_RED        = ::COLOUR_RED,
155 		SPBC_LIGHT_BLUE = ::COLOUR_LIGHT_BLUE,
156 		SPBC_GREEN      = ::COLOUR_GREEN,
157 		SPBC_DARK_GREEN = ::COLOUR_DARK_GREEN,
158 		SPBC_BLUE       = ::COLOUR_BLUE,
159 		SPBC_CREAM      = ::COLOUR_CREAM,
160 		SPBC_MAUVE      = ::COLOUR_MAUVE,
161 		SPBC_PURPLE     = ::COLOUR_PURPLE,
162 		SPBC_ORANGE     = ::COLOUR_ORANGE,
163 		SPBC_BROWN      = ::COLOUR_BROWN,
164 		SPBC_GREY       = ::COLOUR_GREY,
165 		SPBC_WHITE      = ::COLOUR_WHITE,
166 	};
167 
168 	/**
169 	 * Check whether this is a valid story page ID.
170 	 * @param story_page_id The StoryPageID to check.
171 	 * @return True if and only if this story page is valid.
172 	 */
173 	static bool IsValidStoryPage(StoryPageID story_page_id);
174 
175 	/**
176 	 * Check whether this is a valid story page element ID.
177 	 * @param story_page_element_id The StoryPageElementID to check.
178 	 * @return True if and only if this story page element is valid.
179 	 */
180 	static bool IsValidStoryPageElement(StoryPageElementID story_page_element_id);
181 
182 	/**
183 	 * Create a new story page.
184 	 * @param company The company to create the story page for, or ScriptCompany::COMPANY_INVALID for all.
185 	 * @param title Page title (can be either a raw string, a ScriptText object, or null).
186 	 * @return The new StoryPageID, or STORY_PAGE_INVALID if it failed.
187 	 * @pre No ScriptCompanyMode may be in scope.
188 	 * @pre company == COMPANY_INVALID || ResolveCompanyID(company) != COMPANY_INVALID.
189 	 */
190 	static StoryPageID New(ScriptCompany::CompanyID company, Text *title);
191 
192 	/**
193 	 * Create a new story page element.
194 	 * @param story_page_id The page id of the story page which the page element should be appended to.
195 	 * @param type Which page element type to create.
196 	 * @param reference A reference value to the object that is referred to by some page element types.
197 	 *                  When type is SPET_GOAL, this is the goal ID.
198 	 *                  When type is SPET_LOCATION, this is the TileIndex.
199 	 *                  When type is a button, this is additional parameters for the button,
200 	 *                  use the #BuildPushButtonReference, #BuildTileButtonReference, or #BuildVehicleButtonReference functions to make the values.
201 	 * @param text The body text of page elements that allow custom text. (SPET_TEXT and SPET_LOCATION)
202 	 * @return The new StoryPageElementID, or STORY_PAGE_ELEMENT_INVALID if it failed.
203 	 * @pre No ScriptCompanyMode may be in scope.
204 	 * @pre IsValidStoryPage(story_page).
205 	 * @pre (type != SPET_TEXT && type != SPET_LOCATION) || (text != nullptr && len(text) != 0).
206 	 * @pre type != SPET_LOCATION || ScriptMap::IsValidTile(reference).
207 	 * @pre type != SPET_GOAL || ScriptGoal::IsValidGoal(reference).
208 	 * @pre if type is SPET_GOAL and story_page is a global page, then referenced goal must be global.
209 	 */
210 	static StoryPageElementID NewElement(StoryPageID story_page_id, StoryPageElementType type, uint32 reference, Text *text);
211 
212 	/**
213 	 * Update the content of a page element
214 	 * @param story_page_element_id The page id of the story page which the page element should be appended to.
215 	 * @param reference A reference value to the object that is referred to by some page element types. See also NewElement.
216 	 * @param text The body text of page elements that allow custom text. See also NewElement.
217 	 * @return True if the action succeeded.
218 	 * @pre No ScriptCompanyMode may be in scope.
219 	 * @pre IsValidStoryPage(story_page).
220 	 * @pre (type != SPET_TEXT && type != SPET_LOCATION) || (text != nullptr && len(text) != 0).
221 	 * @pre type != SPET_LOCATION || ScriptMap::IsValidTile(reference).
222 	 * @pre type != SPET_GOAL || ScriptGoal::IsValidGoal(reference).
223 	 * @pre if type is SPET_GOAL and story_page is a global page, then referenced goal must be global.
224 	 */
225 	static bool UpdateElement(StoryPageElementID story_page_element_id, uint32 reference, Text *text);
226 
227 	/**
228 	 * Get story page sort value. Each page has a sort value that is internally assigned and used
229 	 * to sort the pages in the story book. OpenTTD maintains this number so that the sort order
230 	 * is perceived. This API exist only so that you can sort ScriptStoryPageList the same order
231 	 * as in GUI. You should not use this number for anything else.
232 	 * @param story_page_id The story page to get the sort value of.
233 	 * @return Page sort value.
234 	 */
235 	static uint32 GetPageSortValue(StoryPageID story_page_id);
236 
237 	/**
238 	 * Get story page element sort value. Each page element has a sort value that is internally
239 	 * assigned and used to sort the page elements within a page of the story book. OpenTTD
240 	 * maintains this number so that the sort order is perceived. This API exist only so that
241 	 * you can sort ScriptStoryPageList the same order as in GUI. You should not use this number
242 	 * for anything else.
243 	 * @param story_page_element_id The story page element to get the sort value of.
244 	 * @return Page element sort value.
245 	 */
246 	static uint32 GetPageElementSortValue(StoryPageElementID story_page_element_id);
247 
248 	/**
249 	 * Get the company which the page belongs to. If the page is global,
250 	 * ScriptCompany::COMPANY_INVALID is returned.
251 	 * @param story_page_id The story page to get the company for.
252 	 * @return owner company or ScriptCompany::COMPANY_INVALID
253 	 * @pre IsValidStoryPage(story_page_id).
254 	 */
255 	static ScriptCompany::CompanyID GetCompany(StoryPageID story_page_id);
256 
257 	/**
258 	 * Get the page date which is displayed at the top of each page.
259 	 * @param story_page_id The story page to get the date of.
260 	 * @return The date
261 	 * @pre IsValidStoryPage(story_page_id).
262 	 */
263 	static ScriptDate::Date GetDate(StoryPageID story_page_id);
264 
265 	/**
266 	 * Update date of a story page. The date is shown in the top left of the page
267 	 * @param story_page_id The story page to set the date for.
268 	 * @param date Date to display at the top of story page or ScriptDate::DATE_INVALID to disable showing date on this page. (also, @see ScriptDate)
269 	 * @return True if the action succeeded.
270 	 * @pre No ScriptCompanyMode may be in scope.
271 	 * @pre IsValidStoryPage(story_page_id).
272 	 */
273 	static bool SetDate(StoryPageID story_page_id, ScriptDate::Date date);
274 
275 	/**
276 	 * Update title of a story page. The title is shown in the page selector drop down.
277 	 * @param story_page_id The story page to update.
278 	 * @param title Page title (can be either a raw string, a ScriptText object, or null).
279 	 * @return True if the action succeeded.
280 	 * @pre No ScriptCompanyMode may be in scope.
281 	 * @pre IsValidStoryPage(story_page_id).
282 	 */
283 	static bool SetTitle(StoryPageID story_page_id, Text *title);
284 
285 	/**
286 	 * Opens the Story Book if not yet open and selects the given page.
287 	 * @param story_page_id The story page to update. If it is a global page, clients of all
288 	 * companies are affecetd. Otherwise only the clients of the company which the page belongs
289 	 * to are affected.
290 	 * @return True if the action succeeded.
291 	 * @pre No ScriptCompanyMode may be in scope.
292 	 * @pre IsValidStoryPage(story_page_id).
293 	 */
294 	static bool Show(StoryPageID story_page_id);
295 
296 	/**
297 	 * Remove a story page and all the page elements
298 	 * associated with it.
299 	 * @param story_page_id The story page to remove.
300 	 * @return True if the action succeeded.
301 	 * @pre No ScriptCompanyMode may be in scope.
302 	 * @pre IsValidStoryPage(story_page_id).
303 	 */
304 	static bool Remove(StoryPageID story_page_id);
305 
306 	/**
307 	 * Removes a story page element.
308 	 * @param story_page_element_id The story page element to remove.
309 	 * @return True if the action succeeded.
310 	 * @pre No ScriptCompanyMode may be in scope.
311 	 * @pre IsValidStoryPageElement(story_page_element_id).
312 	 */
313 	static bool RemoveElement(StoryPageElementID story_page_element_id);
314 
315 	/**
316 	 * Create a reference value for SPET_BUTTON_PUSH element parameters.
317 	 * @param colour The colour for the face of the button.
318 	 * @return A reference value usable with the #NewElement and #UpdateElement functions.
319 	 */
320 	static StoryPageButtonFormatting MakePushButtonReference(StoryPageButtonColour colour, StoryPageButtonFlags flags);
321 
322 	/**
323 	 * Create a reference value for SPET_BUTTON_TILE element parameters.
324 	 * @param colour The colour for the face of the button.
325 	 * @param cursor The mouse cursor to use when the player clicks the button and the game is ready for the player to select a tile.
326 	 * @return A reference value usable with the #NewElement and #UpdateElement functions.
327 	 */
328 	static StoryPageButtonFormatting MakeTileButtonReference(StoryPageButtonColour colour, StoryPageButtonFlags flags, StoryPageButtonCursor cursor);
329 
330 	/**
331 	 * Create a reference value for SPET_BUTTON_VEHICLE element parameters.
332 	 * @param colour  The colour for the face of the button.
333 	 * @param cursor  The mouse cursor to use when the player clicks the button and the game is ready for the player to select a vehicle.
334 	 * @param vehtype The type of vehicle that will be selectable, or \c VT_INVALID to allow all types.
335 	 * @return A reference value usable with the #NewElement and #UpdateElement functions.
336 	 */
337 	static StoryPageButtonFormatting MakeVehicleButtonReference(StoryPageButtonColour colour, StoryPageButtonFlags flags, StoryPageButtonCursor cursor, ScriptVehicle::VehicleType vehtype);
338 };
339 
340 #endif /* SCRIPT_STORY_HPP */
341 
342