OpenTTD
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 "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"
24 
25 #include "safeguards.h"
26 
27 
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;
32 
33 StoryPageElementPool _story_page_element_pool("StoryPageElement");
34 StoryPagePool _story_page_pool("StoryPage");
37 
38 
48 static bool VerifyElementContentParameters(StoryPageID page_id, StoryPageElementType type, TileIndex tile, uint32 reference, const char *text)
49 {
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;
65  }
66 
67  return true;
68 }
69 
78 static void UpdateElement(StoryPageElement &pe, TileIndex tile, uint32 reference, const char *text)
79 {
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();
92  }
93 }
94 
105 CommandCost CmdCreateStoryPage(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
106 {
107  if (!StoryPage::CanAllocateItem()) return CMD_ERROR;
108 
109  CompanyID company = (CompanyID)GB(p1, 0, 8);
110 
111  if (_current_company != OWNER_DEITY) return CMD_ERROR;
112  if (company != INVALID_COMPANY && !Company::IsValidID(company)) return CMD_ERROR;
113 
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;
118  }
119 
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);
128  }
129 
132 
133  _new_story_page_id = s->index;
134  _story_page_next_sort_value++;
135  }
136 
137  return CommandCost();
138 }
139 
151 CommandCost CmdCreateStoryPageElement(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
152 {
154 
155  StoryPageID page_id = (StoryPageID)GB(p1, 0, 16);
156  StoryPageElementType type = Extract<StoryPageElementType, 16, 8>(p1);
157 
158  /* Allow at most 128 elements per page. */
159  uint16 element_count = 0;
161  if (iter->page == page_id) element_count++;
162  }
163  if (element_count >= 128) return CMD_ERROR;
164 
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;
168 
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;
173  }
174 
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);
180 
182 
183  _new_story_page_element_id = pe->index;
184  _story_page_element_next_sort_value++;
185  }
186 
187  return CommandCost();
188 }
189 
201 CommandCost CmdUpdateStoryPageElement(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
202 {
203  StoryPageElementID page_element_id = (StoryPageElementID)GB(p1, 0, 16);
204 
205  if (_current_company != OWNER_DEITY) return CMD_ERROR;
206  if (!StoryPageElement::IsValidID(page_element_id)) return CMD_ERROR;
207 
208  StoryPageElement *pe = StoryPageElement::Get(page_element_id);
209  StoryPageID page_id = pe->page;
210  StoryPageElementType type = pe->type;
211 
212  if (!VerifyElementContentParameters(page_id, type, tile, p2, text)) return CMD_ERROR;
213 
214  if (flags & DC_EXEC) {
215  UpdateElement(*pe, tile, p2, text);
217  }
218 
219  return CommandCost();
220 }
221 
231 CommandCost CmdSetStoryPageTitle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
232 {
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;
236 
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);
244  }
245 
247  }
248 
249  return CommandCost();
250 }
251 
261 CommandCost CmdSetStoryPageDate(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
262 {
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;
267 
268  if (flags & DC_EXEC) {
269  StoryPage *p = StoryPage::Get(page_id);
270  p->date = date;
271 
273  }
274 
275  return CommandCost();
276 }
277 
288 CommandCost CmdShowStoryPage(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
289 {
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;
293 
294  if (flags & DC_EXEC) {
295  StoryPage *g = StoryPage::Get(page_id);
297  }
298 
299  return CommandCost();
300 }
310 CommandCost CmdRemoveStoryPage(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
311 {
312  if (_current_company != OWNER_DEITY) return CMD_ERROR;
313  StoryPageID page_id = (StoryPageID)p1;
314  if (!StoryPage::IsValidID(page_id)) return CMD_ERROR;
315 
316  if (flags & DC_EXEC) {
317  StoryPage *p = StoryPage::Get(page_id);
318 
320  if (pe->page == p->index) {
321  delete pe;
322  }
323  }
324 
325  delete p;
326 
329  }
330 
331  return CommandCost();
332 }
333 
343 CommandCost CmdRemoveStoryPageElement(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
344 {
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;
348 
349  if (flags & DC_EXEC) {
350  StoryPageElement *pe = StoryPageElement::Get(page_element_id);
351  StoryPageID page_id = pe->page;
352 
353  delete pe;
354 
356  }
357 
358  return CommandCost();
359 }
360 
Owner
Enum for all companies/owners.
Definition: company_type.h:18
Definition of stuff that is very close to a company, like the company struct itself.
An element that references a tile along with a one-line text.
Definition: story_base.h:30
StoryPageID page
Id of the page which the page element belongs to.
Definition: story_base.h:46
static Titem * Get(size_t index)
Returns Titem with given index.
Definition: pool_type.hpp:291
Functions related to dates.
uint16 GoalID
ID of a goal.
Definition: goal_type.h:31
static const CommandCost CMD_ERROR
Define a default return value for a failed command.
Definition: command_func.h:23
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:45
Date date
Date when the page was created.
Definition: story_base.h:66
CommandCost CmdUpdateStoryPageElement(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
Update a new story page element.
Definition: story.cpp:201
Tindex index
Index of this pool item.
Definition: pool_type.hpp:189
char * title
Title of story page.
Definition: story_base.h:69
Helper functions to extract data from command parameters.
Common return value for all commands.
Definition: command_type.h:23
Struct about story page elements.
Definition: story_base.h:44
static bool IsValidTile(TileIndex tile)
Checks if a tile is valid.
Definition: tile_map.h:161
uint32 referenced_id
Id of referenced object (location, goal etc.)
Definition: story_base.h:49
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:3334
CommandCost CmdRemoveStoryPage(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
Remove a story page and associated story page elements.
Definition: story.cpp:310
Struct about stories, current and completed.
Definition: story_base.h:64
Functions related to low-level strings.
Some methods of Pool are placed here in order to reduce compilation time and binary size...
CommandCost CmdRemoveStoryPageElement(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
Remove a story page element.
Definition: story.cpp:343
DoCommandFlag
List of flags for a command.
Definition: command_type.h:342
uint16 StoryPageElementID
ID of a story page element.
Definition: story_type.h:15
Definition of base types and functions in a cross-platform compatible way.
A number of safeguards to prevent using unsafe methods.
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:48
char * stredup(const char *s, const char *last)
Create a duplicate of the given string.
Definition: string.cpp:136
StoryPageElementType type
Type of page element.
Definition: story_base.h:47
size_t items
Number of used indexes (non-nullptr)
Definition: pool_type.hpp:93
CommandCost CmdSetStoryPageTitle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
Update title of a story page.
Definition: story.cpp:231
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:65
basic types related to goals
CommandCost CmdCreateStoryPageElement(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
Create a new story page element.
Definition: story.cpp:151
Base class for all pools.
Definition: pool_type.hpp:82
CommandCost CmdSetStoryPageDate(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
Update date of a story page.
Definition: story.cpp:261
An element that references a goal.
Definition: story_base.h:31
#define INSTANTIATE_POOL_METHODS(name)
Force instantiation of pool methods so we don&#39;t get linker errors.
Definition: pool_func.hpp:224
execute the given command
Definition: command_type.h:344
A text element.
Definition: story_base.h:29
Functions related to companies.
An invalid company.
Definition: company_type.h:30
CommandCost CmdShowStoryPage(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
Display a story page for all clients that are allowed to view the story page.
Definition: story.cpp:288
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:78
static Pool::IterateWrapper< Titem > Iterate(size_t from=0)
Returns an iterable ensemble of all valid Titem.
Definition: pool_type.hpp:340
static bool StrEmpty(const char *s)
Check if a string buffer is empty.
Definition: string_func.h:57
uint32 TileIndex
The index/ID of a Tile.
Definition: tile_type.h:78
static size_t GetNumItems()
Returns number of valid items in the pool.
Definition: pool_type.hpp:321
Story book; Window numbers:
Definition: window_type.h:289
static uint GB(const T x, const uint8 s, const uint8 n)
Fetch n bits from x, started at bit s.
CommandCost CmdCreateStoryPage(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
Create a new story page.
Definition: story.cpp:105
Goal base class.
static bool CanAllocateItem(size_t n=1)
Helper functions so we can use PoolItem::Function() instead of _poolitem_pool.Function() ...
Definition: pool_type.hpp:261
Functions related to commands.
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:750
Main toolbar (the long bar at the top); Window numbers:
Definition: window_type.h:51
CompanyID _current_company
Company currently doing an action.
Definition: company_cmd.cpp:45
static bool IsValidID(size_t index)
Tests whether given index can be used to get valid (non-nullptr) Titem.
Definition: pool_type.hpp:280
StoryPage base class.
int32 Date
The type to store our dates in.
Definition: date_type.h:14
static void free(const void *ptr)
Version of the standard free that accepts const pointers.
Definition: depend.cpp:129
char * text
Static content text of page element.
Definition: story_base.h:50
Map writing/reading functions for tiles.
Window functions not directly related to making/drawing windows.
GUI functions that shouldn&#39;t be here.
Date _date
Current date in days (day counter)
Definition: date.cpp:26
uint16 StoryPageID
ID of a story page.
Definition: story_type.h:16
CompanyID company
StoryPage is for a specific company; INVALID_COMPANY if it is global.
Definition: story_base.h:67
CompanyID _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
Definition: company_cmd.cpp:44
The object is owned by a superuser / goal script.
Definition: company_type.h:27
StoryPageElementType
Definition: story_base.h:28
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:3316