OpenTTD Source  13.2.1
story.cpp
Go to the documentation of this file.
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 
10 #include "stdafx.h"
11 #include "story_base.h"
12 #include "core/pool_func.hpp"
13 #include "command_func.h"
14 #include "company_base.h"
15 #include "company_func.h"
16 #include "string_func.h"
17 #include "date_func.h"
18 #include "tile_map.h"
19 #include "goal_type.h"
20 #include "goal_base.h"
21 #include "window_func.h"
22 #include "gui.h"
23 #include "vehicle_base.h"
24 #include "game/game.hpp"
25 #include "script/api/script_story_page.hpp"
26 #include "script/api/script_event_types.hpp"
27 #include "story_cmd.h"
28 
29 #include "safeguards.h"
30 
31 
32 uint32 _story_page_element_next_sort_value;
33 uint32 _story_page_next_sort_value;
34 
35 StoryPageElementPool _story_page_element_pool("StoryPageElement");
36 StoryPagePool _story_page_pool("StoryPage");
39 
40 
50 static bool VerifyElementContentParameters(StoryPageID page_id, StoryPageElementType type, TileIndex tile, uint32 reference, const char *text)
51 {
52  StoryPageButtonData button_data{ reference };
53 
54  switch (type) {
55  case SPET_TEXT:
56  if (StrEmpty(text)) return false;
57  break;
58  case SPET_LOCATION:
59  if (StrEmpty(text)) return false;
60  if (!IsValidTile(tile)) return false;
61  break;
62  case SPET_GOAL:
63  if (!Goal::IsValidID((GoalID)reference)) return false;
64  /* Reject company specific goals on global pages */
65  if (StoryPage::Get(page_id)->company == INVALID_COMPANY && Goal::Get((GoalID)reference)->company != INVALID_COMPANY) return false;
66  break;
67  case SPET_BUTTON_PUSH:
68  if (!button_data.ValidateColour()) return false;
69  return true;
70  case SPET_BUTTON_TILE:
71  if (!button_data.ValidateColour()) return false;
72  if (!button_data.ValidateCursor()) return false;
73  return true;
75  if (!button_data.ValidateColour()) return false;
76  if (!button_data.ValidateCursor()) return false;
77  if (!button_data.ValidateVehicleType()) return false;
78  return true;
79  default:
80  return false;
81  }
82 
83  return true;
84 }
85 
94 static void UpdateElement(StoryPageElement &pe, TileIndex tile, uint32 reference, const char *text)
95 {
96  switch (pe.type) {
97  case SPET_TEXT:
98  pe.text = stredup(text);
99  break;
100  case SPET_LOCATION:
101  pe.text = stredup(text);
102  pe.referenced_id = tile;
103  break;
104  case SPET_GOAL:
105  pe.referenced_id = (GoalID)reference;
106  break;
107  case SPET_BUTTON_PUSH:
108  case SPET_BUTTON_TILE:
109  case SPET_BUTTON_VEHICLE:
110  pe.text = stredup(text);
111  pe.referenced_id = reference;
112  break;
113  default: NOT_REACHED();
114  }
115 }
116 
118 void StoryPageButtonData::SetColour(Colours button_colour)
119 {
120  assert(button_colour < COLOUR_END);
121  SB(this->referenced_id, 0, 8, button_colour);
122 }
123 
124 void StoryPageButtonData::SetFlags(StoryPageButtonFlags flags)
125 {
126  SB(this->referenced_id, 24, 8, flags);
127 }
128 
131 {
132  assert(cursor < SPBC_END);
133  SB(this->referenced_id, 8, 8, cursor);
134 }
135 
138 {
139  assert(vehtype == VEH_INVALID || vehtype < VEH_COMPANY_END);
140  SB(this->referenced_id, 16, 8, vehtype);
141 }
142 
145 {
146  Colours colour = (Colours)GB(this->referenced_id, 0, 8);
147  if (!IsValidColours(colour)) return INVALID_COLOUR;
148  return colour;
149 }
150 
151 StoryPageButtonFlags StoryPageButtonData::GetFlags() const
152 {
153  return (StoryPageButtonFlags)GB(this->referenced_id, 24, 8);
154 }
155 
158 {
159  StoryPageButtonCursor cursor = (StoryPageButtonCursor)GB(this->referenced_id, 8, 8);
160  if (!IsValidStoryPageButtonCursor(cursor)) return INVALID_SPBC;
161  return cursor;
162 }
163 
166 {
167  return (VehicleType)GB(this->referenced_id, 16, 8);
168 }
169 
172 {
173  return GB(this->referenced_id, 0, 8) < COLOUR_END;
174 }
175 
176 bool StoryPageButtonData::ValidateFlags() const
177 {
178  byte flags = GB(this->referenced_id, 24, 8);
179  /* Don't allow float left and right together */
180  if ((flags & SPBF_FLOAT_LEFT) && (flags & SPBF_FLOAT_RIGHT)) return false;
181  /* Don't allow undefined flags */
182  if (flags & ~(SPBF_FLOAT_LEFT | SPBF_FLOAT_RIGHT)) return false;
183  return true;
184 }
185 
188 {
189  return GB(this->referenced_id, 8, 8) < SPBC_END;
190 }
191 
194 {
195  byte vehtype = GB(this->referenced_id, 16, 8);
196  return vehtype == VEH_INVALID || vehtype < VEH_COMPANY_END;
197 }
198 
206 std::tuple<CommandCost, StoryPageID> CmdCreateStoryPage(DoCommandFlag flags, CompanyID company, const std::string &text)
207 {
208  if (!StoryPage::CanAllocateItem()) return { CMD_ERROR, INVALID_STORY_PAGE };
209 
210  if (_current_company != OWNER_DEITY) return { CMD_ERROR, INVALID_STORY_PAGE };
211  if (company != INVALID_COMPANY && !Company::IsValidID(company)) return { CMD_ERROR, INVALID_STORY_PAGE };
212 
213  if (flags & DC_EXEC) {
214  if (_story_page_pool.items == 0) {
215  /* Initialize the next sort value variable. */
216  _story_page_next_sort_value = 0;
217  }
218 
219  StoryPage *s = new StoryPage();
220  s->sort_value = _story_page_next_sort_value;
221  s->date = _date;
222  s->company = company;
223  if (text.empty()) {
224  s->title = nullptr;
225  } else {
226  s->title = stredup(text.c_str());
227  }
228 
231 
232  _story_page_next_sort_value++;
233  return { CommandCost(), s->index };
234  }
235 
236  return { CommandCost(), INVALID_STORY_PAGE };
237 }
238 
249 std::tuple<CommandCost, StoryPageElementID> CmdCreateStoryPageElement(DoCommandFlag flags, TileIndex tile, StoryPageID page_id, StoryPageElementType type, uint32 reference, const std::string &text)
250 {
251  if (!StoryPageElement::CanAllocateItem()) return { CMD_ERROR, INVALID_STORY_PAGE_ELEMENT };
252 
253  /* Allow at most 128 elements per page. */
254  uint16 element_count = 0;
256  if (iter->page == page_id) element_count++;
257  }
258  if (element_count >= 128) return { CMD_ERROR, INVALID_STORY_PAGE_ELEMENT };
259 
260  if (_current_company != OWNER_DEITY) return { CMD_ERROR, INVALID_STORY_PAGE_ELEMENT };
261  if (!StoryPage::IsValidID(page_id)) return { CMD_ERROR, INVALID_STORY_PAGE_ELEMENT };
262  if (!VerifyElementContentParameters(page_id, type, tile, reference, text.c_str())) return { CMD_ERROR, INVALID_STORY_PAGE_ELEMENT };
263 
264 
265  if (flags & DC_EXEC) {
266  if (_story_page_element_pool.items == 0) {
267  /* Initialize the next sort value variable. */
268  _story_page_element_next_sort_value = 0;
269  }
270 
272  pe->sort_value = _story_page_element_next_sort_value;
273  pe->type = type;
274  pe->page = page_id;
275  UpdateElement(*pe, tile, reference, text.c_str());
276 
278 
279  _story_page_element_next_sort_value++;
280  return { CommandCost(), pe->index };
281  }
282 
283  return { CommandCost(), INVALID_STORY_PAGE_ELEMENT };
284 }
285 
295 CommandCost CmdUpdateStoryPageElement(DoCommandFlag flags, TileIndex tile, StoryPageElementID page_element_id, uint32 reference, const std::string &text)
296 {
297  if (_current_company != OWNER_DEITY) return CMD_ERROR;
298  if (!StoryPageElement::IsValidID(page_element_id)) return CMD_ERROR;
299 
300  StoryPageElement *pe = StoryPageElement::Get(page_element_id);
301  StoryPageID page_id = pe->page;
302  StoryPageElementType type = pe->type;
303 
304  if (!VerifyElementContentParameters(page_id, type, tile, reference, text.c_str())) return CMD_ERROR;
305 
306  if (flags & DC_EXEC) {
307  UpdateElement(*pe, tile, reference, text.c_str());
309  }
310 
311  return CommandCost();
312 }
313 
321 CommandCost CmdSetStoryPageTitle(DoCommandFlag flags, StoryPageID page_id, const std::string &text)
322 {
323  if (_current_company != OWNER_DEITY) return CMD_ERROR;
324  if (!StoryPage::IsValidID(page_id)) return CMD_ERROR;
325 
326  if (flags & DC_EXEC) {
327  StoryPage *p = StoryPage::Get(page_id);
328  free(p->title);
329  if (text.empty()) {
330  p->title = nullptr;
331  } else {
332  p->title = stredup(text.c_str());
333  }
334 
336  }
337 
338  return CommandCost();
339 }
340 
349 {
350  if (_current_company != OWNER_DEITY) return CMD_ERROR;
351  if (!StoryPage::IsValidID(page_id)) return CMD_ERROR;
352 
353  if (flags & DC_EXEC) {
354  StoryPage *p = StoryPage::Get(page_id);
355  p->date = date;
356 
358  }
359 
360  return CommandCost();
361 }
362 
371 {
372  if (_current_company != OWNER_DEITY) return CMD_ERROR;
373  if (!StoryPage::IsValidID(page_id)) return CMD_ERROR;
374 
375  if (flags & DC_EXEC) {
376  StoryPage *g = StoryPage::Get(page_id);
378  }
379 
380  return CommandCost();
381 }
389 {
390  if (_current_company != OWNER_DEITY) return CMD_ERROR;
391  if (!StoryPage::IsValidID(page_id)) return CMD_ERROR;
392 
393  if (flags & DC_EXEC) {
394  StoryPage *p = StoryPage::Get(page_id);
395 
397  if (pe->page == p->index) {
398  delete pe;
399  }
400  }
401 
402  delete p;
403 
406  }
407 
408  return CommandCost();
409 }
410 
418 {
419  if (_current_company != OWNER_DEITY) return CMD_ERROR;
420  if (!StoryPageElement::IsValidID(page_element_id)) return CMD_ERROR;
421 
422  if (flags & DC_EXEC) {
423  StoryPageElement *pe = StoryPageElement::Get(page_element_id);
424  StoryPageID page_id = pe->page;
425 
426  delete pe;
427 
429  }
430 
431  return CommandCost();
432 }
433 
443 {
444  if (!StoryPageElement::IsValidID(page_element_id)) return CMD_ERROR;
445  const StoryPageElement *const pe = StoryPageElement::Get(page_element_id);
446 
447  /* Check the player belongs to the company that owns the page. */
448  const StoryPage *const sp = StoryPage::Get(pe->page);
449  if (sp->company != INVALID_COMPANY && sp->company != _current_company) return CMD_ERROR;
450 
451  switch (pe->type) {
452  case SPET_BUTTON_PUSH:
453  /* No validation required */
454  if (flags & DC_EXEC) Game::NewEvent(new ScriptEventStoryPageButtonClick(_current_company, pe->page, page_element_id));
455  break;
456  case SPET_BUTTON_TILE:
457  if (!IsValidTile(tile)) return CMD_ERROR;
458  if (flags & DC_EXEC) Game::NewEvent(new ScriptEventStoryPageTileSelect(_current_company, pe->page, page_element_id, tile));
459  break;
460  case SPET_BUTTON_VEHICLE:
461  if (!Vehicle::IsValidID(reference)) return CMD_ERROR;
462  if (flags & DC_EXEC) Game::NewEvent(new ScriptEventStoryPageVehicleSelect(_current_company, pe->page, page_element_id, reference));
463  break;
464  default:
465  /* Invalid page element type, not a button. */
466  return CMD_ERROR;
467  }
468 
469  return CommandCost();
470 }
471 
game.hpp
StoryPageElement::sort_value
uint32 sort_value
A number that increases for every created story page element. Used for sorting. The id of a story pag...
Definition: story_base.h:151
SPET_TEXT
@ SPET_TEXT
A text element.
Definition: story_base.h:31
InvalidateWindowData
void InvalidateWindowData(WindowClass cls, WindowNumber number, int data, bool gui_scope)
Mark window data of the window of a given class and specific window number as invalid (in need of re-...
Definition: window.cpp:3254
Pool::PoolItem<&_story_page_pool >::Get
static Titem * Get(size_t index)
Returns Titem with given index.
Definition: pool_type.hpp:337
GB
static uint GB(const T x, const uint8 s, const uint8 n)
Fetch n bits from x, started at bit s.
Definition: bitmath_func.hpp:32
command_func.h
CMD_ERROR
static const CommandCost CMD_ERROR
Define a default return value for a failed command.
Definition: command_func.h:28
StoryPageButtonData::GetCursor
StoryPageButtonCursor GetCursor() const
Get the mouse cursor used while waiting for input for the button.
Definition: story.cpp:157
ShowStoryBook
void ShowStoryBook(CompanyID company, uint16 page_id=INVALID_STORY_PAGE)
Raise or create the story book window for company, at page page_id.
Definition: story_gui.cpp:1057
company_base.h
StoryPageButtonFlags
StoryPageButtonFlags
Flags available for buttons.
Definition: story_base.h:45
StoryPageElementType
StoryPageElementType
Definition: story_base.h:30
StoryPageButtonData::SetCursor
void SetCursor(StoryPageButtonCursor cursor)
Set the mouse cursor used while waiting for input for the button.
Definition: story.cpp:130
CmdCreateStoryPage
std::tuple< CommandCost, StoryPageID > CmdCreateStoryPage(DoCommandFlag flags, CompanyID company, const std::string &text)
Create a new story page.
Definition: story.cpp:206
goal_type.h
Pool::PoolItem::index
Tindex index
Index of this pool item.
Definition: pool_type.hpp:235
SPET_BUTTON_PUSH
@ SPET_BUTTON_PUSH
A push button that triggers an immediate event.
Definition: story_base.h:34
TileIndex
The index/ID of a Tile.
Definition: tile_type.h:85
vehicle_base.h
goal_base.h
SPET_GOAL
@ SPET_GOAL
An element that references a goal.
Definition: story_base.h:33
StoryPage::sort_value
uint32 sort_value
A number that increases for every created story page. Used for sorting. The id of a story page is the...
Definition: story_base.h:171
CmdShowStoryPage
CommandCost CmdShowStoryPage(DoCommandFlag flags, StoryPageID page_id)
Display a story page for all clients that are allowed to view the story page.
Definition: story.cpp:370
StoryPageButtonData::SetColour
void SetColour(Colours button_colour)
Set the button background colour.
Definition: story.cpp:118
Owner
Owner
Enum for all companies/owners.
Definition: company_type.h:18
DC_EXEC
@ DC_EXEC
execute the given command
Definition: command_type.h:357
DoCommandFlag
DoCommandFlag
List of flags for a command.
Definition: command_type.h:355
CmdSetStoryPageDate
CommandCost CmdSetStoryPageDate(DoCommandFlag flags, StoryPageID page_id, Date date)
Update date of a story page.
Definition: story.cpp:348
StoryPageElement::referenced_id
uint32 referenced_id
Id of referenced object (location, goal etc.)
Definition: story_base.h:155
StoryPageButtonData::ValidateVehicleType
bool ValidateVehicleType() const
Verity that the data stored a valid VehicleType value.
Definition: story.cpp:193
SPET_BUTTON_VEHICLE
@ SPET_BUTTON_VEHICLE
A button that allows the player to select a vehicle, and triggers an event wih the vehicle.
Definition: story_base.h:36
StoryPageButtonData::ValidateCursor
bool ValidateCursor() const
Verify that the data stores a valid StoryPageButtonCursor value.
Definition: story.cpp:187
WC_STORY_BOOK
@ WC_STORY_BOOK
Story book; Window numbers:
Definition: window_type.h:289
tile_map.h
SPET_BUTTON_TILE
@ SPET_BUTTON_TILE
A button that allows the player to select a tile, and triggers an event with the tile.
Definition: story_base.h:35
StoryPageElement::type
StoryPageElementType type
Type of page element.
Definition: story_base.h:153
CommandCost
Common return value for all commands.
Definition: command_type.h:24
CmdUpdateStoryPageElement
CommandCost CmdUpdateStoryPageElement(DoCommandFlag flags, TileIndex tile, StoryPageElementID page_element_id, uint32 reference, const std::string &text)
Update a new story page element.
Definition: story.cpp:295
_date
Date _date
Current date in days (day counter)
Definition: date.cpp:28
VEH_COMPANY_END
@ VEH_COMPANY_END
Last company-ownable type.
Definition: vehicle_type.h:29
Pool::items
size_t items
Number of used indexes (non-nullptr)
Definition: pool_type.hpp:92
StoryPageID
uint16 StoryPageID
ID of a story page.
Definition: story_type.h:16
StoryPageButtonData::GetVehicleType
VehicleType GetVehicleType() const
Get the type of vehicles that are accepted by the button.
Definition: story.cpp:165
SB
static T SB(T &x, const uint8 s, const uint8 n, const U d)
Set n bits in x starting at bit s to d.
Definition: bitmath_func.hpp:58
Date
int32 Date
The type to store our dates in.
Definition: date_type.h:14
StoryPage
Struct about stories, current and completed.
Definition: story_base.h:170
Game::NewEvent
static void NewEvent(class ScriptEvent *event)
Queue a new event for a Game Script.
Definition: game_core.cpp:146
_local_company
CompanyID _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
Definition: company_cmd.cpp:46
safeguards.h
VEH_INVALID
@ VEH_INVALID
Non-existing type of vehicle.
Definition: vehicle_type.h:35
IsValidTile
static bool IsValidTile(TileIndex tile)
Checks if a tile is valid.
Definition: tile_map.h:161
StrEmpty
static bool StrEmpty(const char *s)
Check if a string buffer is empty.
Definition: string_func.h:67
SPET_LOCATION
@ SPET_LOCATION
An element that references a tile along with a one-line text.
Definition: story_base.h:32
StoryPageButtonCursor
StoryPageButtonCursor
Mouse cursors usable by story page buttons.
Definition: story_base.h:53
CmdStoryPageButton
CommandCost CmdStoryPageButton(DoCommandFlag flags, TileIndex tile, StoryPageElementID page_element_id, VehicleID reference)
Clicked/used a button on a story page.
Definition: story.cpp:442
IsValidStoryPageButtonCursor
static bool IsValidStoryPageButtonCursor(StoryPageButtonCursor cursor)
Checks if a StoryPageButtonCursor value is valid.
Definition: story_base.h:122
date_func.h
stdafx.h
VehicleType
VehicleType
Available vehicle types.
Definition: vehicle_type.h:21
StoryPage::title
char * title
Title of story page.
Definition: story_base.h:175
StoryPageButtonData::SetVehicleType
void SetVehicleType(VehicleType vehtype)
Set the type of vehicles that are accepted by the button.
Definition: story.cpp:137
VerifyElementContentParameters
static bool VerifyElementContentParameters(StoryPageID page_id, StoryPageElementType type, TileIndex tile, uint32 reference, const char *text)
This helper for Create/Update PageElement Cmd procedure verifies if the page element parameters are c...
Definition: story.cpp:50
string_func.h
_current_company
CompanyID _current_company
Company currently doing an action.
Definition: company_cmd.cpp:47
Pool::PoolItem<&_story_page_element_pool >::Iterate
static Pool::IterateWrapper< Titem > Iterate(size_t from=0)
Returns an iterable ensemble of all valid Titem.
Definition: pool_type.hpp:386
Pool
Base class for all pools.
Definition: pool_type.hpp:81
CmdSetStoryPageTitle
CommandCost CmdSetStoryPageTitle(DoCommandFlag flags, StoryPageID page_id, const std::string &text)
Update title of a story page.
Definition: story.cpp:321
Pool::PoolItem<&_story_page_pool >::GetNumItems
static size_t GetNumItems()
Returns number of valid items in the pool.
Definition: pool_type.hpp:367
InvalidateWindowClassesData
void InvalidateWindowClassesData(WindowClass cls, int data, bool gui_scope)
Mark window data of all windows of a given class as invalid (in need of re-computing) Note that by de...
Definition: window.cpp:3271
story_cmd.h
StoryPageElementID
uint16 StoryPageElementID
ID of a story page element.
Definition: story_type.h:15
StoryPageButtonData::GetColour
Colours GetColour() const
Get the button background colour.
Definition: story.cpp:144
Pool::PoolItem<&_story_page_pool >::CanAllocateItem
static bool CanAllocateItem(size_t n=1)
Helper functions so we can use PoolItem::Function() instead of _poolitem_pool.Function()
Definition: pool_type.hpp:307
StoryPageElement
Struct about story page elements.
Definition: story_base.h:150
UpdateElement
static void UpdateElement(StoryPageElement &pe, TileIndex tile, uint32 reference, const char *text)
This helper for Create/Update PageElement Cmd procedure updates a page element with new content data.
Definition: story.cpp:94
OWNER_DEITY
@ OWNER_DEITY
The object is owned by a superuser / goal script.
Definition: company_type.h:27
company_func.h
INSTANTIATE_POOL_METHODS
#define INSTANTIATE_POOL_METHODS(name)
Force instantiation of pool methods so we don't get linker errors.
Definition: pool_func.hpp:224
stredup
char * stredup(const char *s, const char *last)
Create a duplicate of the given string.
Definition: string.cpp:138
VehicleID
uint32 VehicleID
The type all our vehicle IDs have.
Definition: vehicle_type.h:16
window_func.h
INVALID_COMPANY
@ INVALID_COMPANY
An invalid company.
Definition: company_type.h:30
StoryPageElement::text
char * text
Static content text of page element.
Definition: story_base.h:156
gui.h
StoryPageButtonData
Helper to construct packed "id" values for button-type StoryPageElement.
Definition: story_base.h:128
Pool::PoolItem<&_goal_pool >::IsValidID
static bool IsValidID(size_t index)
Tests whether given index can be used to get valid (non-nullptr) Titem.
Definition: pool_type.hpp:326
StoryPageButtonData::ValidateColour
bool ValidateColour() const
Verify that the data stored a valid Colour value.
Definition: story.cpp:171
pool_func.hpp
CmdCreateStoryPageElement
std::tuple< CommandCost, StoryPageElementID > CmdCreateStoryPageElement(DoCommandFlag flags, TileIndex tile, StoryPageID page_id, StoryPageElementType type, uint32 reference, const std::string &text)
Create a new story page element.
Definition: story.cpp:249
free
static void free(const void *ptr)
Version of the standard free that accepts const pointers.
Definition: stdafx.h:470
story_base.h
GoalID
uint16 GoalID
ID of a goal.
Definition: goal_type.h:38
CmdRemoveStoryPageElement
CommandCost CmdRemoveStoryPageElement(DoCommandFlag flags, StoryPageElementID page_element_id)
Remove a story page element.
Definition: story.cpp:417
WC_MAIN_TOOLBAR
@ WC_MAIN_TOOLBAR
Main toolbar (the long bar at the top); Window numbers:
Definition: window_type.h:51
StoryPage::date
Date date
Date when the page was created.
Definition: story_base.h:172
StoryPage::company
CompanyID company
StoryPage is for a specific company; INVALID_COMPANY if it is global.
Definition: story_base.h:173
IsValidColours
static bool IsValidColours(Colours colours)
Checks if a Colours value is valid.
Definition: gfx_func.h:222
StoryPageElement::page
StoryPageID page
Id of the page which the page element belongs to.
Definition: story_base.h:152
CmdRemoveStoryPage
CommandCost CmdRemoveStoryPage(DoCommandFlag flags, StoryPageID page_id)
Remove a story page and associated story page elements.
Definition: story.cpp:388