OpenTTD
story.cpp
Go to the documentation of this file.
1 /* $Id: story.cpp 27560 2016-05-11 20:48:46Z matthijs $ */
2 
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  */
9 
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"
26 
27 #include "safeguards.h"
28 
29 
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;
34 
35 StoryPageElementPool _story_page_element_pool("StoryPageElement");
36 StoryPagePool _story_page_pool("StoryPage");
39 
50 static bool VerifyElementContentParameters(StoryPageID page_id, StoryPageElementType type, TileIndex tile, uint32 reference, const char *text)
51 {
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;
67  }
68 
69  return true;
70 }
71 
80 static void UpdateElement(StoryPageElement &pe, TileIndex tile, uint32 reference, const char *text)
81 {
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();
94  }
95 }
96 
107 CommandCost CmdCreateStoryPage(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
108 {
109  if (!StoryPage::CanAllocateItem()) return CMD_ERROR;
110 
111  CompanyID company = (CompanyID)GB(p1, 0, 8);
112 
113  if (_current_company != OWNER_DEITY) return CMD_ERROR;
114  if (company != INVALID_COMPANY && !Company::IsValidID(company)) return CMD_ERROR;
115 
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;
120  }
121 
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 = NULL;
128  } else {
129  s->title = stredup(text);
130  }
131 
134 
135  _new_story_page_id = s->index;
136  _story_page_next_sort_value++;
137  }
138 
139  return CommandCost();
140 }
141 
153 CommandCost CmdCreateStoryPageElement(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
154 {
156 
157  StoryPageID page_id = (CompanyID)GB(p1, 0, 16);
158  StoryPageElementType type = Extract<StoryPageElementType, 16, 8>(p1);
159 
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++;
165  }
166  if (element_count >= 128) return CMD_ERROR;
167 
168  if (_current_company != OWNER_DEITY) return CMD_ERROR;
169  if (!StoryPage::IsValidID(page_id)) return CMD_ERROR;
170  if (!VerifyElementContentParameters(page_id, type, tile, p2, text)) return CMD_ERROR;
171 
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;
176  }
177 
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);
183 
185 
186  _new_story_page_element_id = pe->index;
187  _story_page_element_next_sort_value++;
188  }
189 
190  return CommandCost();
191 }
192 
204 CommandCost CmdUpdateStoryPageElement(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
205 {
206  StoryPageElementID page_element_id = (StoryPageElementID)GB(p1, 0, 16);
207 
208  if (_current_company != OWNER_DEITY) return CMD_ERROR;
209  if (!StoryPageElement::IsValidID(page_element_id)) return CMD_ERROR;
210 
211  StoryPageElement *pe = StoryPageElement::Get(page_element_id);
212  StoryPageID page_id = pe->page;
213  StoryPageElementType type = pe->type;
214 
215  if (!VerifyElementContentParameters(page_id, type, tile, p2, text)) return CMD_ERROR;
216 
217  if (flags & DC_EXEC) {
218  UpdateElement(*pe, tile, p2, text);
220  }
221 
222  return CommandCost();
223 }
224 
234 CommandCost CmdSetStoryPageTitle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
235 {
236  if (_current_company != OWNER_DEITY) return CMD_ERROR;
237  StoryPageID page_id = (StoryPageID)GB(p1, 0, 16);
238  if (!StoryPage::IsValidID(page_id)) return CMD_ERROR;
239 
240  if (flags & DC_EXEC) {
241  StoryPage *p = StoryPage::Get(page_id);
242  free(p->title);
243  if (StrEmpty(text)) {
244  p->title = NULL;
245  } else {
246  p->title = stredup(text);
247  }
248 
250  }
251 
252  return CommandCost();
253 }
254 
264 CommandCost CmdSetStoryPageDate(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
265 {
266  if (_current_company != OWNER_DEITY) return CMD_ERROR;
267  StoryPageID page_id = (StoryPageID)GB(p1, 0, 16);
268  if (!StoryPage::IsValidID(page_id)) return CMD_ERROR;
269  Date date = (Date)p2;
270 
271  if (flags & DC_EXEC) {
272  StoryPage *p = StoryPage::Get(page_id);
273  p->date = date;
274 
276  }
277 
278  return CommandCost();
279 }
280 
291 CommandCost CmdShowStoryPage(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
292 {
293  if (_current_company != OWNER_DEITY) return CMD_ERROR;
294  StoryPageID page_id = (StoryPageID)GB(p1, 0, 16);
295  if (!StoryPage::IsValidID(page_id)) return CMD_ERROR;
296 
297  if (flags & DC_EXEC) {
298  StoryPage *g = StoryPage::Get(page_id);
300  }
301 
302  return CommandCost();
303 }
313 CommandCost CmdRemoveStoryPage(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
314 {
315  if (_current_company != OWNER_DEITY) return CMD_ERROR;
316  StoryPageID page_id = (StoryPageID)p1;
317  if (!StoryPage::IsValidID(page_id)) return CMD_ERROR;
318 
319  if (flags & DC_EXEC) {
320  StoryPage *p = StoryPage::Get(page_id);
321 
322  StoryPageElement *pe;
323  FOR_ALL_STORY_PAGE_ELEMENTS(pe) {
324  if (pe->page == p->index) {
325  delete pe;
326  }
327  }
328 
329  delete p;
330 
333  }
334 
335  return CommandCost();
336 }
337 
347 CommandCost CmdRemoveStoryPageElement(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
348 {
349  if (_current_company != OWNER_DEITY) return CMD_ERROR;
350  StoryPageElementID page_element_id = (StoryPageElementID)p1;
351  if (!StoryPageElement::IsValidID(page_element_id)) return CMD_ERROR;
352 
353  if (flags & DC_EXEC) {
354  StoryPageElement *pe = StoryPageElement::Get(page_element_id);
355  StoryPageID page_id = pe->page;
356 
357  delete pe;
358 
360  }
361 
362  return CommandCost();
363 }
364