Fix ICU iterators on leading/trailing whitespace
[openttd/fttd.git] / src / goal.cpp
blob66a83911ba0ae232a6554e87e50c76ced618a52b
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 goal.cpp Handling of goals. */
12 #include "stdafx.h"
13 #include "company_func.h"
14 #include "industry.h"
15 #include "town.h"
16 #include "window_func.h"
17 #include "goal_base.h"
18 #include "core/pool_func.hpp"
19 #include "game/game.hpp"
20 #include "command_func.h"
21 #include "company_base.h"
22 #include "story_base.h"
23 #include "string_func.h"
24 #include "gui.h"
25 #include "network/network.h"
28 GoalID _new_goal_id;
30 template<> Goal::Pool Goal::PoolItem::pool ("Goal");
31 INSTANTIATE_POOL_METHODS(Goal)
33 /**
34 * Create a new goal.
35 * @param tile unused.
36 * @param flags type of operation
37 * @param p1 various bitstuffed elements
38 * - p1 = (bit 0 - 7) - GoalType of destination.
39 * - p1 = (bit 8 - 15) - Company for which this goal is.
40 * @param p2 GoalTypeID of destination.
41 * @param text Text of the goal.
42 * @return the cost of this operation or an error
44 CommandCost CmdCreateGoal(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
46 if (!Goal::CanAllocateItem()) return CMD_ERROR;
48 GoalType type = (GoalType)GB(p1, 0, 8);
49 CompanyID company = (CompanyID)GB(p1, 8, 8);
51 if (_current_company != OWNER_DEITY) return CMD_ERROR;
52 if (StrEmpty(text)) return CMD_ERROR;
53 if (company != INVALID_COMPANY && !Company::IsValidID(company)) return CMD_ERROR;
55 switch (type) {
56 case GT_NONE:
57 if (p2 != 0) return CMD_ERROR;
58 break;
60 case GT_TILE:
61 if (!IsValidTile(p2)) return CMD_ERROR;
62 break;
64 case GT_INDUSTRY:
65 if (!Industry::IsValidID(p2)) return CMD_ERROR;
66 break;
68 case GT_TOWN:
69 if (!Town::IsValidID(p2)) return CMD_ERROR;
70 break;
72 case GT_COMPANY:
73 if (!Company::IsValidID(p2)) return CMD_ERROR;
74 break;
76 case GT_STORY_PAGE: {
77 if (!StoryPage::IsValidID(p2)) return CMD_ERROR;
78 CompanyByte story_company = StoryPage::Get(p2)->company;
79 if (company == INVALID_COMPANY ? story_company != INVALID_COMPANY : story_company != INVALID_COMPANY && story_company != company) return CMD_ERROR;
80 break;
83 default: return CMD_ERROR;
86 if (flags & DC_EXEC) {
87 Goal *g = new Goal();
88 g->type = type;
89 g->dst = p2;
90 g->company = company;
91 g->text = strdup(text);
92 g->progress = NULL;
93 g->completed = false;
95 if (g->company == INVALID_COMPANY) {
96 InvalidateWindowClassesData(WC_GOALS_LIST);
97 } else {
98 InvalidateWindowData(WC_GOALS_LIST, g->company);
100 if (Goal::GetNumItems() == 1) InvalidateWindowData(WC_MAIN_TOOLBAR, 0);
102 _new_goal_id = g->index;
105 return CommandCost();
109 * Remove a goal.
110 * @param tile unused.
111 * @param flags type of operation
112 * @param p1 GoalID to remove.
113 * @param p2 unused.
114 * @param text unused.
115 * @return the cost of this operation or an error
117 CommandCost CmdRemoveGoal(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
119 if (_current_company != OWNER_DEITY) return CMD_ERROR;
120 if (!Goal::IsValidID(p1)) return CMD_ERROR;
122 if (flags & DC_EXEC) {
123 Goal *g = Goal::Get(p1);
124 CompanyID c = g->company;
125 delete g;
127 if (c == INVALID_COMPANY) {
128 InvalidateWindowClassesData(WC_GOALS_LIST);
129 } else {
130 InvalidateWindowData(WC_GOALS_LIST, c);
132 if (Goal::GetNumItems() == 0) InvalidateWindowData(WC_MAIN_TOOLBAR, 0);
135 return CommandCost();
139 * Update goal text of a goal.
140 * @param tile unused.
141 * @param flags type of operation
142 * @param p1 GoalID to update.
143 * @param p2 unused
144 * @param text Text of the goal.
145 * @return the cost of this operation or an error
147 CommandCost CmdSetGoalText(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
149 if (_current_company != OWNER_DEITY) return CMD_ERROR;
150 if (!Goal::IsValidID(p1)) return CMD_ERROR;
151 if (StrEmpty(text)) return CMD_ERROR;
153 if (flags & DC_EXEC) {
154 Goal *g = Goal::Get(p1);
155 free(g->text);
156 g->text = strdup(text);
158 if (g->company == INVALID_COMPANY) {
159 InvalidateWindowClassesData(WC_GOALS_LIST);
160 } else {
161 InvalidateWindowData(WC_GOALS_LIST, g->company);
165 return CommandCost();
169 * Update progress text of a goal.
170 * @param tile unused.
171 * @param flags type of operation
172 * @param p1 GoalID to update.
173 * @param p2 unused
174 * @param text Progress text of the goal.
175 * @return the cost of this operation or an error
177 CommandCost CmdSetGoalProgress(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
179 if (_current_company != OWNER_DEITY) return CMD_ERROR;
180 if (!Goal::IsValidID(p1)) return CMD_ERROR;
182 if (flags & DC_EXEC) {
183 Goal *g = Goal::Get(p1);
184 free(g->progress);
185 if (StrEmpty(text)) {
186 g->progress = NULL;
187 } else {
188 g->progress = strdup(text);
191 if (g->company == INVALID_COMPANY) {
192 InvalidateWindowClassesData(WC_GOALS_LIST);
193 } else {
194 InvalidateWindowData(WC_GOALS_LIST, g->company);
198 return CommandCost();
202 * Update completed state of a goal.
203 * @param tile unused.
204 * @param flags type of operation
205 * @param p1 GoalID to update.
206 * @param p2 completed state. If goal is completed, set to 1, otherwise 0.
207 * @param text unused
208 * @return the cost of this operation or an error
210 CommandCost CmdSetGoalCompleted(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
212 if (_current_company != OWNER_DEITY) return CMD_ERROR;
213 if (!Goal::IsValidID(p1)) return CMD_ERROR;
215 if (flags & DC_EXEC) {
216 Goal *g = Goal::Get(p1);
217 g->completed = p2 == 1;
219 if (g->company == INVALID_COMPANY) {
220 InvalidateWindowClassesData(WC_GOALS_LIST);
221 } else {
222 InvalidateWindowData(WC_GOALS_LIST, g->company);
226 return CommandCost();
230 * Ask a goal related question
231 * @param tile unused.
232 * @param flags type of operation
233 * @param p1 various bitstuffed elements
234 * - p1 = (bit 0 - 15) - Unique ID to use for this question.
235 * - p1 = (bit 16 - 23) - Company for which this question is.
236 * @param p2 Buttons of the question.
237 * @param text Text of the question.
238 * @return the cost of this operation or an error
240 CommandCost CmdGoalQuestion(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
242 uint16 uniqueid = (GoalType)GB(p1, 0, 16);
243 CompanyID company = (CompanyID)GB(p1, 16, 8);
244 byte type = GB(p1, 24, 8);
246 if (_current_company != OWNER_DEITY) return CMD_ERROR;
247 if (StrEmpty(text)) return CMD_ERROR;
248 if (company != INVALID_COMPANY && !Company::IsValidID(company)) return CMD_ERROR;
249 if (CountBits(p2) < 1 || CountBits(p2) > 3) return CMD_ERROR;
250 if (p2 >= (1 << GOAL_QUESTION_BUTTON_COUNT)) return CMD_ERROR;
251 if (type >= GOAL_QUESTION_TYPE_COUNT) return CMD_ERROR;
253 if (flags & DC_EXEC) {
254 if ((company != INVALID_COMPANY && company == _local_company) || (company == INVALID_COMPANY && Company::IsValidID(_local_company))) ShowGoalQuestion(uniqueid, type, p2, text);
257 return CommandCost();
261 * Reply to a goal question.
262 * @param tile unused.
263 * @param flags type of operation
264 * @param p1 Unique ID to use for this question.
265 * @param p2 Button the company pressed
266 * @param text Text of the question.
267 * @return the cost of this operation or an error
269 CommandCost CmdGoalQuestionAnswer(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
271 if (p1 > UINT16_MAX) return CMD_ERROR;
272 if (p2 >= GOAL_QUESTION_BUTTON_COUNT) return CMD_ERROR;
274 if (_current_company == OWNER_DEITY) {
275 /* It has been requested to close this specific question on all clients */
276 if (flags & DC_EXEC) DeleteWindowById(WC_GOAL_QUESTION, p1);
277 return CommandCost();
280 if (_networking && _local_company == _current_company) {
281 /* Somebody in the same company answered the question. Close the window */
282 if (flags & DC_EXEC) DeleteWindowById(WC_GOAL_QUESTION, p1);
283 if (!_network_server) return CommandCost();
286 if (flags & DC_EXEC) {
287 Game::NewEvent(new ScriptEventGoalQuestionAnswer(p1, (ScriptCompany::CompanyID)(byte)_current_company, (ScriptGoal::QuestionButton)(1 << p2)));
290 return CommandCost();