(svn r25384) -Fix (25344): Correctly invalidate the story window when data changes
[openttd/fttd.git] / src / story.cpp
blob915f44da5812f025532bb5f2f1c66fdf74502dfa
1 /* $Id$ */
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 */
10 /** @file story.cpp Handling of stories. */
12 #include "stdafx.h"
13 #include "story_base.h"
14 #include "core/pool_func.hpp"
15 #include "command_func.h"
16 #include "company_base.h"
17 #include "company_func.h"
18 #include "string_func.h"
19 #include "date_func.h"
20 #include "tile_map.h"
21 #include "goal_type.h"
22 #include "goal_base.h"
23 #include "window_func.h"
24 #include "gui.h"
27 StoryPageElementID _new_story_page_element_id;
28 StoryPageID _new_story_page_id;
29 uint32 _story_page_element_next_sort_value;
30 uint32 _story_page_next_sort_value;
32 StoryPageElementPool _story_page_element_pool("StoryPageElement");
33 StoryPagePool _story_page_pool("StoryPage");
34 INSTANTIATE_POOL_METHODS(StoryPageElement)
35 INSTANTIATE_POOL_METHODS(StoryPage)
37 /**
38 * This helper for Create/Update PageElement Cmd procedure verifies if the page
39 * element parameters are correct for the given page element type.
40 * @param page_id The page id of the page which the page element (will) belong to
41 * @param type The type of the page element to create/update
42 * @param tile The tile parameter of the DoCommand proc
43 * @param reference The reference parameter of the DoCommand proc (p2)
44 * @param text The text parameter of the DoCommand proc
45 * @return true, if and only if the given parameters are valid for the given page elment type and page id.
47 static bool VerifyElementContentParameters(uint32 page_id, StoryPageElementType type, TileIndex tile, uint32 reference, const char *text)
49 switch (type) {
50 case SPET_TEXT:
51 if (StrEmpty(text)) return false;
52 break;
53 case SPET_LOCATION:
54 if (StrEmpty(text)) return false;
55 if (!IsValidTile(tile)) return false;
56 break;
57 case SPET_GOAL:
58 if (!Goal::IsValidID((GoalID)reference)) return false;
59 /* Reject company specific goals on global pages */
60 if (StoryPage::Get(page_id)->company == INVALID_COMPANY && Goal::Get((GoalID)reference)->company != INVALID_COMPANY) return false;
61 break;
62 default:
63 return false;
66 return true;
69 /**
70 * This helper for Create/Update PageElement Cmd procedure updates a page
71 * element with new content data.
72 * @param pe The page element to update
73 * @param tile The tile parameter of the DoCommand proc
74 * @param reference The reference parameter of the DoCommand proc (p2)
75 * @param text The text parameter of the DoCommand proc
77 static void UpdateElement(StoryPageElement &pe, TileIndex tile, uint32 reference, const char *text)
79 switch (pe.type) {
80 case SPET_TEXT:
81 pe.text = strdup(text);
82 break;
83 case SPET_LOCATION:
84 pe.text = strdup(text);
85 pe.referenced_id = tile;
86 break;
87 case SPET_GOAL:
88 pe.referenced_id = (GoalID)reference;
89 break;
93 /**
94 * Create a new story page.
95 * @param tile unused.
96 * @param flags type of operation
97 * @param p1 various bitstuffed elements
98 * - p1 = (bit 0 - 7) - Company for which this story page belongs to.
99 * @param p2 unused.
100 * @param text Title of the story page. Null is allowed in wich case a generic page title is provided by OpenTTD.
101 * @return the cost of this operation or an error
103 CommandCost CmdCreateStoryPage(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
105 if (!StoryPage::CanAllocateItem()) return CMD_ERROR;
107 CompanyID company = (CompanyID)GB(p1, 0, 8);
109 if (_current_company != OWNER_DEITY) return CMD_ERROR;
110 if (company != INVALID_COMPANY && !Company::IsValidID(company)) return CMD_ERROR;
112 if (flags & DC_EXEC) {
113 if (_story_page_pool.items == 0) {
114 /* Initialize the next sort value variable. */
115 _story_page_next_sort_value = 0;
118 StoryPage *s = new StoryPage();
119 s->sort_value = _story_page_next_sort_value;
120 s->date = _date;
121 s->company = company;
122 if (StrEmpty(text)) {
123 s->title = NULL;
124 } else {
125 s->title = strdup(text);
128 InvalidateWindowClassesData(WC_STORY_BOOK, -1);
130 _new_story_page_id = s->index;
131 _story_page_next_sort_value++;
134 return CommandCost();
138 * Create a new story page element.
139 * @param tile Tile location if it is a location page element, otherwise unused.
140 * @param flags type of operation
141 * @param p1 various bitstuffed elements
142 * - p1 = (bit 0 - 15) - The page which the element belongs to.
143 * (bit 16 - 31) - Page element type
144 * @param p2 Id of referenced object
145 * @param text Text content in case it is a text or location page element
146 * @return the cost of this operation or an error
148 CommandCost CmdCreateStoryPageElement(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
150 if (!StoryPageElement::CanAllocateItem()) return CMD_ERROR;
152 StoryPageID page_id = (CompanyID)GB(p1, 0, 16);
153 StoryPageElementType type = (StoryPageElementType) GB(p1, 16, 16);
155 /* Allow at most 128 elements per page. */
156 uint16 element_count = 0;
157 StoryPageElement *iter;
158 FOR_ALL_STORY_PAGE_ELEMENTS(iter) {
159 if (iter->page == page_id) element_count++;
161 if (element_count >= 128) return CMD_ERROR;
163 if (_current_company != OWNER_DEITY) return CMD_ERROR;
164 if (!StoryPage::IsValidID(page_id)) return CMD_ERROR;
165 if (!VerifyElementContentParameters(page_id, type, tile, p2, text)) return CMD_ERROR;
167 if (flags & DC_EXEC) {
168 if (_story_page_element_pool.items == 0) {
169 /* Initialize the next sort value variable. */
170 _story_page_element_next_sort_value = 0;
173 StoryPageElement *pe = new StoryPageElement();
174 pe->sort_value = _story_page_element_next_sort_value;
175 pe->type = type;
176 pe->page = page_id;
177 UpdateElement(*pe, tile, p2, text);
179 InvalidateWindowClassesData(WC_STORY_BOOK, page_id);
181 _new_story_page_element_id = pe->index;
182 _story_page_element_next_sort_value++;
185 return CommandCost();
189 * Update a new story page element.
190 * @param tile Tile location if it is a location page element, otherwise unused.
191 * @param flags type of operation
192 * @param p1 various bitstuffed elements
193 * - p1 = (bit 0 - 15) - The page element to update.
194 * (bit 16 - 31) - unused
195 * @param p2 Id of referenced object
196 * @param text Text content in case it is a text or location page element
197 * @return the cost of this operation or an error
199 CommandCost CmdUpdateStoryPageElement(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
201 StoryPageElementID page_element_id = (StoryPageElementID)GB(p1, 0, 16);
203 if (_current_company != OWNER_DEITY) return CMD_ERROR;
204 if (!StoryPageElement::IsValidID(page_element_id)) return CMD_ERROR;
206 StoryPageElement *pe = StoryPageElement::Get(page_element_id);
207 StoryPageID page_id = pe->page;
208 StoryPageElementType type = pe->type;
210 if (!VerifyElementContentParameters(page_id, type, tile, p2, text)) return CMD_ERROR;
212 if (flags & DC_EXEC) {
213 UpdateElement(*pe, tile, p2, text);
214 InvalidateWindowClassesData(WC_STORY_BOOK, pe->page);
217 return CommandCost();
221 * Update title of a story page.
222 * @param tile unused.
223 * @param flags type of operation
224 * @param p1 StoryPageID to update.
225 * @param p2 unused
226 * @param text title text of the story page.
227 * @return the cost of this operation or an error
229 CommandCost CmdSetStoryPageTitle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
231 if (_current_company != OWNER_DEITY) return CMD_ERROR;
232 StoryPageID page_id = (StoryPageID)p1;
233 if (!StoryPage::IsValidID(page_id)) return CMD_ERROR;
235 if (flags & DC_EXEC) {
236 StoryPage *p = StoryPage::Get(page_id);
237 free(p->title);
238 if (StrEmpty(text)) {
239 p->title = NULL;
240 } else {
241 p->title = strdup(text);
244 InvalidateWindowClassesData(WC_STORY_BOOK, page_id);
247 return CommandCost();
251 * Display a story page for all clients that are allowed to
252 * view the story page.
253 * @param tile unused.
254 * @param flags type of operation
255 * @param p1 StoryPageID to show.
256 * @param p2 unused
257 * @param text unused
258 * @return the cost of this operation or an error
260 CommandCost CmdShowStoryPage(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
262 if (_current_company != OWNER_DEITY) return CMD_ERROR;
263 if (!StoryPage::IsValidID(p1)) return CMD_ERROR;
265 if (flags & DC_EXEC) {
266 StoryPage *g = StoryPage::Get(p1);
267 if ((g->company != INVALID_COMPANY && g->company == _local_company) || (g->company == INVALID_COMPANY && Company::IsValidID(_local_company))) ShowStoryBook(_local_company, p1);
270 return CommandCost();
273 * Remove a story page and associated story page elements.
274 * @param tile unused.
275 * @param flags type of operation
276 * @param p1 StoryPageID to remove.
277 * @param p2 unused.
278 * @param text unused.
279 * @return the cost of this operation or an error
281 CommandCost CmdRemoveStoryPage(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
283 if (_current_company != OWNER_DEITY) return CMD_ERROR;
284 StoryPageID page_id = (StoryPageID)p1;
285 if (!StoryPage::IsValidID(page_id)) return CMD_ERROR;
287 if (flags & DC_EXEC) {
288 StoryPage *p = StoryPage::Get(page_id);
290 StoryPageElement *pe;
291 FOR_ALL_STORY_PAGE_ELEMENTS(pe) {
292 if (pe->page == p->index) {
293 delete pe;
297 delete p;
299 InvalidateWindowClassesData(WC_STORY_BOOK, -1);
302 return CommandCost();