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/>.
10 /** @file goal.cpp Handling of goals. */
13 #include "company_func.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"
25 #include "network/network.h"
30 GoalPool
_goal_pool("Goal");
31 INSTANTIATE_POOL_METHODS(Goal
)
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
;
57 if (p2
!= 0) return CMD_ERROR
;
61 if (!IsValidTile(p2
)) return CMD_ERROR
;
65 if (!Industry::IsValidID(p2
)) return CMD_ERROR
;
69 if (!Town::IsValidID(p2
)) return CMD_ERROR
;
73 if (!Company::IsValidID(p2
)) return CMD_ERROR
;
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
;
83 default: return CMD_ERROR
;
86 if (flags
& DC_EXEC
) {
91 g
->text
= strdup(text
);
95 InvalidateWindowData(WC_GOALS_LIST
, 0);
96 if (Goal::GetNumItems() == 1) InvalidateWindowData(WC_MAIN_TOOLBAR
, 0);
98 _new_goal_id
= g
->index
;
101 return CommandCost();
106 * @param tile unused.
107 * @param flags type of operation
108 * @param p1 GoalID to remove.
110 * @param text unused.
111 * @return the cost of this operation or an error
113 CommandCost
CmdRemoveGoal(TileIndex tile
, DoCommandFlag flags
, uint32 p1
, uint32 p2
, const char *text
)
115 if (_current_company
!= OWNER_DEITY
) return CMD_ERROR
;
116 if (!Goal::IsValidID(p1
)) return CMD_ERROR
;
118 if (flags
& DC_EXEC
) {
119 Goal
*g
= Goal::Get(p1
);
122 InvalidateWindowData(WC_GOALS_LIST
, 0);
123 if (Goal::GetNumItems() == 0) InvalidateWindowData(WC_MAIN_TOOLBAR
, 0);
126 return CommandCost();
130 * Update goal text of a goal.
131 * @param tile unused.
132 * @param flags type of operation
133 * @param p1 GoalID to update.
135 * @param text Text of the goal.
136 * @return the cost of this operation or an error
138 CommandCost
CmdSetGoalText(TileIndex tile
, DoCommandFlag flags
, uint32 p1
, uint32 p2
, const char *text
)
140 if (_current_company
!= OWNER_DEITY
) return CMD_ERROR
;
141 if (!Goal::IsValidID(p1
)) return CMD_ERROR
;
142 if (StrEmpty(text
)) return CMD_ERROR
;
144 if (flags
& DC_EXEC
) {
145 Goal
*g
= Goal::Get(p1
);
147 g
->text
= strdup(text
);
149 InvalidateWindowData(WC_GOALS_LIST
, 0);
152 return CommandCost();
156 * Update progress text of a goal.
157 * @param tile unused.
158 * @param flags type of operation
159 * @param p1 GoalID to update.
161 * @param text Progress text of the goal.
162 * @return the cost of this operation or an error
164 CommandCost
CmdSetGoalProgress(TileIndex tile
, DoCommandFlag flags
, uint32 p1
, uint32 p2
, const char *text
)
166 if (_current_company
!= OWNER_DEITY
) return CMD_ERROR
;
167 if (!Goal::IsValidID(p1
)) return CMD_ERROR
;
169 if (flags
& DC_EXEC
) {
170 Goal
*g
= Goal::Get(p1
);
172 if (StrEmpty(text
)) {
175 g
->progress
= strdup(text
);
178 InvalidateWindowData(WC_GOALS_LIST
, 0);
181 return CommandCost();
185 * Update completed state of a goal.
186 * @param tile unused.
187 * @param flags type of operation
188 * @param p1 GoalID to update.
189 * @param p2 completed state. If goal is completed, set to 1, otherwise 0.
191 * @return the cost of this operation or an error
193 CommandCost
CmdSetGoalCompleted(TileIndex tile
, DoCommandFlag flags
, uint32 p1
, uint32 p2
, const char *text
)
195 if (_current_company
!= OWNER_DEITY
) return CMD_ERROR
;
196 if (!Goal::IsValidID(p1
)) return CMD_ERROR
;
198 if (flags
& DC_EXEC
) {
199 Goal
*g
= Goal::Get(p1
);
200 g
->completed
= p2
== 1;
202 InvalidateWindowData(WC_GOALS_LIST
, 0);
205 return CommandCost();
209 * Ask a goal related question
210 * @param tile unused.
211 * @param flags type of operation
212 * @param p1 various bitstuffed elements
213 * - p1 = (bit 0 - 15) - Unique ID to use for this question.
214 * - p1 = (bit 16 - 23) - Company for which this question is.
215 * @param p2 Buttons of the question.
216 * @param text Text of the question.
217 * @return the cost of this operation or an error
219 CommandCost
CmdGoalQuestion(TileIndex tile
, DoCommandFlag flags
, uint32 p1
, uint32 p2
, const char *text
)
221 uint16 uniqueid
= (GoalType
)GB(p1
, 0, 16);
222 CompanyID company
= (CompanyID
)GB(p1
, 16, 8);
223 byte type
= GB(p1
, 24, 8);
225 if (_current_company
!= OWNER_DEITY
) return CMD_ERROR
;
226 if (StrEmpty(text
)) return CMD_ERROR
;
227 if (company
!= INVALID_COMPANY
&& !Company::IsValidID(company
)) return CMD_ERROR
;
228 if (CountBits(p2
) < 1 || CountBits(p2
) > 3) return CMD_ERROR
;
229 if (p2
>= (1 << GOAL_QUESTION_BUTTON_COUNT
)) return CMD_ERROR
;
230 if (type
>= GOAL_QUESTION_TYPE_COUNT
) return CMD_ERROR
;
232 if (flags
& DC_EXEC
) {
233 if ((company
!= INVALID_COMPANY
&& company
== _local_company
) || (company
== INVALID_COMPANY
&& Company::IsValidID(_local_company
))) ShowGoalQuestion(uniqueid
, type
, p2
, text
);
236 return CommandCost();
240 * Reply to a goal question.
241 * @param tile unused.
242 * @param flags type of operation
243 * @param p1 Unique ID to use for this question.
244 * @param p2 Button the company pressed
245 * @param text Text of the question.
246 * @return the cost of this operation or an error
248 CommandCost
CmdGoalQuestionAnswer(TileIndex tile
, DoCommandFlag flags
, uint32 p1
, uint32 p2
, const char *text
)
250 if (p1
> UINT16_MAX
) return CMD_ERROR
;
251 if (p2
>= GOAL_QUESTION_BUTTON_COUNT
) return CMD_ERROR
;
253 if (_current_company
== OWNER_DEITY
) {
254 /* It has been requested to close this specific question on all clients */
255 if (flags
& DC_EXEC
) DeleteWindowById(WC_GOAL_QUESTION
, p1
);
256 return CommandCost();
259 if (_networking
&& _local_company
== _current_company
) {
260 /* Somebody in the same company answered the question. Close the window */
261 if (flags
& DC_EXEC
) DeleteWindowById(WC_GOAL_QUESTION
, p1
);
262 if (!_network_server
) return CommandCost();
265 if (flags
& DC_EXEC
) {
266 Game::NewEvent(new ScriptEventGoalQuestionAnswer(p1
, (ScriptCompany::CompanyID
)(byte
)_current_company
, (ScriptGoal::QuestionButton
)(1 << p2
)));
269 return CommandCost();