OpenTTD Source: src/goal.cpp Source File

OpenTTD Source 12.2

goal.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 "company_func.h"
12 #include "industry.h"
13 #include "town.h"
14 #include "window_func.h"
15 #include "goal_base.h"
16 #include "core/pool_func.hpp"
17 #include "game/game.hpp"
18 #include "command_func.h"
19 #include "company_base.h"
20 #include "story_base.h"
21 #include "string_func.h"
22 #include "gui.h"
23 #include "network/network.h"
24 #include "network/network_base.h"
25 #include "network/network_func.h"
26
27 #include "safeguards.h"
28
29
30 GoalID _new_goal_id;
31
32 GoalPool _goal_pool("Goal");
33 INSTANTIATE_POOL_METHODS(Goal)
34
35
46 CommandCost CmdCreateGoal(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text)
47 {
48 if (!Goal::CanAllocateItem()) return CMD_ERROR;
49
50 GoalType type = (GoalType)GB(p1, 0, 8);
51 CompanyID company = (CompanyID)GB(p1, 8, 8);
52
53 if (_current_company != OWNER_DEITY) return CMD_ERROR;
54 if (text.empty()) return CMD_ERROR;
55 if (company != INVALID_COMPANY && !Company::IsValidID(company)) return CMD_ERROR;
56
57 switch (type) {
58 case GT_NONE:
59 if (p2 != 0) return CMD_ERROR;
60 break;
61
62 case GT_TILE:
63 if (!IsValidTile(p2)) return CMD_ERROR;
64 break;
65
66 case GT_INDUSTRY:
67 if (!Industry::IsValidID(p2)) return CMD_ERROR;
68 break;
69
70 case GT_TOWN:
71 if (!Town::IsValidID(p2)) return CMD_ERROR;
72 break;
73
74 case GT_COMPANY:
75 if (!Company::IsValidID(p2)) return CMD_ERROR;
76 break;
77
78 case GT_STORY_PAGE: {
79 if (!StoryPage::IsValidID(p2)) return CMD_ERROR;
80 CompanyID story_company = StoryPage::Get(p2)->company;
81 if (company == INVALID_COMPANY ? story_company != INVALID_COMPANY : story_company != INVALID_COMPANY && story_company != company) return CMD_ERROR;
82 break;
83 }
84
85 default: return CMD_ERROR;
86 }
87
88 if (flags & DC_EXEC) {
89 Goal *g = new Goal();
90 g->type = type;
91 g->dst = p2;
92 g->company = company;
93 g->text = stredup(text.c_str());
94 g->progress = nullptr;
95 g->completed = false;
96
97 if (g->company == INVALID_COMPANY) {
98 InvalidateWindowClassesData(WC_GOALS_LIST);
99 } else {
100 InvalidateWindowData(WC_GOALS_LIST, g->company);
101 }
102 if (Goal::GetNumItems() == 1) InvalidateWindowData(WC_MAIN_TOOLBAR, 0);
103
104 _new_goal_id = g->index;
105 }
106
107 return CommandCost();
108 }
109
119 CommandCost CmdRemoveGoal(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text)
120 {
121 if (_current_company != OWNER_DEITY) return CMD_ERROR;
122 if (!Goal::IsValidID(p1)) return CMD_ERROR;
123
124 if (flags & DC_EXEC) {
125 Goal *g = Goal::Get(p1);
126 CompanyID c = g->company;
127 delete g;
128
129 if (c == INVALID_COMPANY) {
130 InvalidateWindowClassesData(WC_GOALS_LIST);
131 } else {
132 InvalidateWindowData(WC_GOALS_LIST, c);
133 }
134 if (Goal::GetNumItems() == 0) InvalidateWindowData(WC_MAIN_TOOLBAR, 0);
135 }
136
137 return CommandCost();
138 }
139
149 CommandCost CmdSetGoalText(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text)
150 {
151 if (_current_company != OWNER_DEITY) return CMD_ERROR;
152 if (!Goal::IsValidID(p1)) return CMD_ERROR;
153 if (text.empty()) return CMD_ERROR;
154
155 if (flags & DC_EXEC) {
156 Goal *g = Goal::Get(p1);
157 free(g->text);
158 g->text = stredup(text.c_str());
159
160 if (g->company == INVALID_COMPANY) {
161 InvalidateWindowClassesData(WC_GOALS_LIST);
162 } else {
163 InvalidateWindowData(WC_GOALS_LIST, g->company);
164 }
165 }
166
167 return CommandCost();
168 }
169
179 CommandCost CmdSetGoalProgress(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text)
180 {
181 if (_current_company != OWNER_DEITY) return CMD_ERROR;
182 if (!Goal::IsValidID(p1)) return CMD_ERROR;
183
184 if (flags & DC_EXEC) {
185 Goal *g = Goal::Get(p1);
186 free(g->progress);
187 if (text.empty()) {
188 g->progress = nullptr;
189 } else {
190 g->progress = stredup(text.c_str());
191 }
192
193 if (g->company == INVALID_COMPANY) {
194 InvalidateWindowClassesData(WC_GOALS_LIST);
195 } else {
196 InvalidateWindowData(WC_GOALS_LIST, g->company);
197 }
198 }
199
200 return CommandCost();
201 }
202
212 CommandCost CmdSetGoalCompleted(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text)
213 {
214 if (_current_company != OWNER_DEITY) return CMD_ERROR;
215 if (!Goal::IsValidID(p1)) return CMD_ERROR;
216
217 if (flags & DC_EXEC) {
218 Goal *g = Goal::Get(p1);
219 g->completed = p2 == 1;
220
221 if (g->company == INVALID_COMPANY) {
222 InvalidateWindowClassesData(WC_GOALS_LIST);
223 } else {
224 InvalidateWindowData(WC_GOALS_LIST, g->company);
225 }
226 }
227
228 return CommandCost();
229 }
230
245 CommandCost CmdGoalQuestion(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text)
246 {
247 uint16 uniqueid = (uint16)GB(p1, 0, 16);
248 CompanyID company = (CompanyID)GB(p1, 16, 8);
249 ClientID client = (ClientID)GB(p1, 16, 16);
250
251 static_assert(GOAL_QUESTION_BUTTON_COUNT < 29);
252 uint32 button_mask = GB(p2, 0, GOAL_QUESTION_BUTTON_COUNT);
253 byte type = GB(p2, 29, 2);
254 bool is_client = HasBit(p2, 31);
255
256 if (_current_company != OWNER_DEITY) return CMD_ERROR;
257 if (text.empty()) return CMD_ERROR;
258 if (is_client) {
259 /* Only check during pre-flight; the client might have left between
260 * testing and executing. In that case it is fine to just ignore the
261 * fact the client is no longer here. */
262 if (!(flags & DC_EXEC) && _network_server && NetworkClientInfo::GetByClientID(client) == nullptr) return CMD_ERROR;
263 } else {
264 if (company != INVALID_COMPANY && !Company::IsValidID(company)) return CMD_ERROR;
265 }
266 uint min_buttons = (type == GQT_QUESTION ? 1 : 0);
267 if (CountBits(button_mask) < min_buttons || CountBits(button_mask) > 3) return CMD_ERROR;
268 if (type >= GQT_END) return CMD_ERROR;
269
270 if (flags & DC_EXEC) {
271 if (is_client) {
272 if (client != _network_own_client_id) return CommandCost();
273 } else {
274 if (company == INVALID_COMPANY && !Company::IsValidID(_local_company)) return CommandCost();
275 if (company != INVALID_COMPANY && company != _local_company) return CommandCost();
276 }
277 ShowGoalQuestion(uniqueid, type, button_mask, text.c_str());
278 }
279
280 return CommandCost();
281 }
282
292 CommandCost CmdGoalQuestionAnswer(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text)
293 {
294 if (p1 > UINT16_MAX) return CMD_ERROR;
295 if (p2 >= GOAL_QUESTION_BUTTON_COUNT) return CMD_ERROR;
296
297 if (_current_company == OWNER_DEITY) {
298 /* It has been requested to close this specific question on all clients */
299 if (flags & DC_EXEC) CloseWindowById(WC_GOAL_QUESTION, p1);
300 return CommandCost();
301 }
302
303 if (_networking && _local_company == _current_company) {
304 /* Somebody in the same company answered the question. Close the window */
305 if (flags & DC_EXEC) CloseWindowById(WC_GOAL_QUESTION, p1);
306 if (!_network_server) return CommandCost();
307 }
308
309 if (flags & DC_EXEC) {
310 Game::NewEvent(new ScriptEventGoalQuestionAnswer(p1, (ScriptCompany::CompanyID)(byte)_current_company, (ScriptGoal::QuestionButton)(1 << p2)));
311 }
312
313 return CommandCost();
314 }
game.hpp
TileIndex
uint32 TileIndex
The index/ID of a Tile.
Definition: tile_type.h:83
InvalidateWindowData
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:3234
Goal
Struct about goals, current and completed.
Definition: goal_base.h:21
Pool::PoolItem<&_story_page_pool >::Get
static Titem * Get(size_t index)
Returns Titem with given index.
Definition: pool_type.hpp:337
GB
static uint GB(const T x, const uint8 s, const uint8 n)
Fetch n bits from x, started at bit s.
Definition: bitmath_func.hpp:32
command_func.h
CMD_ERROR
static const CommandCost CMD_ERROR
Define a default return value for a failed command.
Definition: command_func.h:23
GT_INDUSTRY
@ GT_INDUSTRY
Destination is an industry.
Definition: goal_type.h:29
company_base.h
_network_server
bool _network_server
network-server is active
Definition: network.cpp:58
Pool::PoolItem::index
Tindex index
Index of this pool item.
Definition: pool_type.hpp:235
HasBit
static bool HasBit(const T x, const uint8 y)
Checks if a bit in a value is set.
Definition: bitmath_func.hpp:103
GT_TILE
@ GT_TILE
Destination is a tile.
Definition: goal_type.h:28
goal_base.h
CmdRemoveGoal
CommandCost CmdRemoveGoal(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text)
Remove a goal.
Definition: goal.cpp:119
town.h
Goal::dst
GoalTypeID dst
Index of type.
Definition: goal_base.h:24
WC_GOALS_LIST
@ WC_GOALS_LIST
Goals list; Window numbers:
Definition: window_type.h:282
Owner
Owner
Enum for all companies/owners.
Definition: company_type.h:18
DC_EXEC
@ DC_EXEC
execute the given command
Definition: command_type.h:348
DoCommandFlag
DoCommandFlag
List of flags for a command.
Definition: command_type.h:346
CmdCreateGoal
CommandCost CmdCreateGoal(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text)
Create a new goal.
Definition: goal.cpp:46
network_base.h
CountBits
static uint CountBits(T value)
Counts the number of set bits in a variable.
Definition: bitmath_func.hpp:251
GT_TOWN
@ GT_TOWN
Destination is a town.
Definition: goal_type.h:30
NetworkClientInfo::GetByClientID
static NetworkClientInfo * GetByClientID(ClientID client_id)
Return the CI given it's client-identifier.
Definition: network.cpp:113
CommandCost
Common return value for all commands.
Definition: command_type.h:23
ClientID
ClientID
'Unique' identifier to be given to clients
Definition: network_type.h:47
CmdGoalQuestionAnswer
CommandCost CmdGoalQuestionAnswer(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text)
Reply to a goal question.
Definition: goal.cpp:292
Game::NewEvent
static void NewEvent(class ScriptEvent *event)
Queue a new event for a Game Script.
Definition: game_core.cpp:141
_local_company
CompanyID _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
Definition: company_cmd.cpp:46
industry.h
safeguards.h
IsValidTile
static bool IsValidTile(TileIndex tile)
Checks if a tile is valid.
Definition: tile_map.h:161
_networking
bool _networking
are we in networking mode?
Definition: network.cpp:57
CmdGoalQuestion
CommandCost CmdGoalQuestion(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text)
Ask a goal related question.
Definition: goal.cpp:245
stdafx.h
GT_NONE
@ GT_NONE
Destination is not linked.
Definition: goal_type.h:27
CmdSetGoalCompleted
CommandCost CmdSetGoalCompleted(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text)
Update completed state of a goal.
Definition: goal.cpp:212
_network_own_client_id
ClientID _network_own_client_id
Our client identifier.
Definition: network.cpp:63
Goal::progress
char * progress
Progress text of the goal.
Definition: goal_base.h:26
string_func.h
_current_company
CompanyID _current_company
Company currently doing an action.
Definition: company_cmd.cpp:47
Pool
Base class for all pools.
Definition: pool_type.hpp:81
GOAL_QUESTION_BUTTON_COUNT
static const uint32 GOAL_QUESTION_BUTTON_COUNT
Amount of buttons available.
Definition: goal_type.h:15
Pool::PoolItem<&_goal_pool >::GetNumItems
static size_t GetNumItems()
Returns number of valid items in the pool.
Definition: pool_type.hpp:367
GT_COMPANY
@ GT_COMPANY
Destination is a company.
Definition: goal_type.h:31
CmdSetGoalText
CommandCost CmdSetGoalText(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text)
Update goal text of a goal.
Definition: goal.cpp:149
Goal::completed
bool completed
Is the goal completed or not?
Definition: goal_base.h:27
InvalidateWindowClassesData
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:3251
Goal::company
CompanyID company
Goal is for a specific company; INVALID_COMPANY if it is global.
Definition: goal_base.h:22
WC_GOAL_QUESTION
@ WC_GOAL_QUESTION
Popup with a set of buttons, designed to ask the user a question from a GameScript.
Definition: window_type.h:129
Pool::PoolItem<&_goal_pool >::CanAllocateItem
static bool CanAllocateItem(size_t n=1)
Helper functions so we can use PoolItem::Function() instead of _poolitem_pool.Function()
Definition: pool_type.hpp:307
GT_STORY_PAGE
@ GT_STORY_PAGE
Destination is a story page.
Definition: goal_type.h:32
OWNER_DEITY
@ OWNER_DEITY
The object is owned by a superuser / goal script.
Definition: company_type.h:27
company_func.h
INSTANTIATE_POOL_METHODS
#define INSTANTIATE_POOL_METHODS(name)
Force instantiation of pool methods so we don't get linker errors.
Definition: pool_func.hpp:224
stredup
char * stredup(const char *s, const char *last)
Create a duplicate of the given string.
Definition: string.cpp:137
network.h
window_func.h
CmdSetGoalProgress
CommandCost CmdSetGoalProgress(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const std::string &text)
Update progress text of a goal.
Definition: goal.cpp:179
CloseWindowById
void CloseWindowById(WindowClass cls, WindowNumber number, bool force)
Close a window by its class and window number (if it is open).
Definition: window.cpp:1176
INVALID_COMPANY
@ INVALID_COMPANY
An invalid company.
Definition: company_type.h:30
gui.h
Pool::PoolItem<&_company_pool >::IsValidID
static bool IsValidID(size_t index)
Tests whether given index can be used to get valid (non-nullptr) Titem.
Definition: pool_type.hpp:326
GoalType
GoalType
Types of goal destinations.
Definition: goal_type.h:26
pool_func.hpp
free
static void free(const void *ptr)
Version of the standard free that accepts const pointers.
Definition: stdafx.h:460
story_base.h
GoalID
uint16 GoalID
ID of a goal.
Definition: goal_type.h:38
WC_MAIN_TOOLBAR
@ WC_MAIN_TOOLBAR
Main toolbar (the long bar at the top); Window numbers:
Definition: window_type.h:50
Goal::type
GoalType type
Type of the goal.
Definition: goal_base.h:23
network_func.h
Goal::text
char * text
Text of the goal.
Definition: goal_base.h:25
ShowGoalQuestion
void ShowGoalQuestion(uint16 id, byte type, uint32 button_mask, const char *question)
Display a goal question.
Definition: goal_gui.cpp:561