OpenTTD Source  20240917-master-g9ab0a47812
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 #include "goal_cmd.h"
27 
28 #include "safeguards.h"
29 
30 
31 GoalPool _goal_pool("Goal");
33 
34 /* static */ bool Goal::IsValidGoalDestination(CompanyID company, GoalType type, GoalTypeID dest)
35 {
36  switch (type) {
37  case GT_NONE:
38  if (dest != 0) return false;
39  break;
40 
41  case GT_TILE:
42  if (!IsValidTile(dest)) return false;
43  break;
44 
45  case GT_INDUSTRY:
46  if (!Industry::IsValidID(dest)) return false;
47  break;
48 
49  case GT_TOWN:
50  if (!Town::IsValidID(dest)) return false;
51  break;
52 
53  case GT_COMPANY:
54  if (!Company::IsValidID(dest)) return false;
55  break;
56 
57  case GT_STORY_PAGE: {
58  if (!StoryPage::IsValidID(dest)) return false;
59  CompanyID story_company = StoryPage::Get(dest)->company;
60  if (company == INVALID_COMPANY ? story_company != INVALID_COMPANY : story_company != INVALID_COMPANY && story_company != company) return false;
61  break;
62  }
63 
64  default: return false;
65  }
66  return true;
67 }
68 
78 std::tuple<CommandCost, GoalID> CmdCreateGoal(DoCommandFlag flags, CompanyID company, GoalType type, GoalTypeID dest, const std::string &text)
79 {
80  if (!Goal::CanAllocateItem()) return { CMD_ERROR, INVALID_GOAL };
81 
83  if (text.empty()) return { CMD_ERROR, INVALID_GOAL };
84  if (company != INVALID_COMPANY && !Company::IsValidID(company)) return { CMD_ERROR, INVALID_GOAL };
85  if (!Goal::IsValidGoalDestination(company, type, dest)) return { CMD_ERROR, INVALID_GOAL };
86 
87  if (flags & DC_EXEC) {
88  Goal *g = new Goal();
89  g->type = type;
90  g->dst = dest;
91  g->company = company;
92  g->text = text;
93  g->completed = false;
94 
95  if (g->company == INVALID_COMPANY) {
97  } else {
99  }
101 
102  return { CommandCost(), g->index };
103  }
104 
105  return { CommandCost(), INVALID_GOAL };
106 }
107 
115 {
116  if (_current_company != OWNER_DEITY) return CMD_ERROR;
117  if (!Goal::IsValidID(goal)) return CMD_ERROR;
118 
119  if (flags & DC_EXEC) {
120  Goal *g = Goal::Get(goal);
121  CompanyID c = g->company;
122  delete g;
123 
124  if (c == INVALID_COMPANY) {
126  } else {
128  }
130  }
131 
132  return CommandCost();
133 }
134 
144 {
145  if (_current_company != OWNER_DEITY) return CMD_ERROR;
146  if (!Goal::IsValidID(goal)) return CMD_ERROR;
147  Goal *g = Goal::Get(goal);
148  if (!Goal::IsValidGoalDestination(g->company, type, dest)) return CMD_ERROR;
149 
150  if (flags & DC_EXEC) {
151  g->type = type;
152  g->dst = dest;
153  }
154 
155  return CommandCost();
156 }
157 
165 CommandCost CmdSetGoalText(DoCommandFlag flags, GoalID goal, const std::string &text)
166 {
167  if (_current_company != OWNER_DEITY) return CMD_ERROR;
168  if (!Goal::IsValidID(goal)) return CMD_ERROR;
169  if (text.empty()) return CMD_ERROR;
170 
171  if (flags & DC_EXEC) {
172  Goal *g = Goal::Get(goal);
173  g->text = text;
174 
175  if (g->company == INVALID_COMPANY) {
177  } else {
179  }
180  }
181 
182  return CommandCost();
183 }
184 
192 CommandCost CmdSetGoalProgress(DoCommandFlag flags, GoalID goal, const std::string &text)
193 {
194  if (_current_company != OWNER_DEITY) return CMD_ERROR;
195  if (!Goal::IsValidID(goal)) return CMD_ERROR;
196 
197  if (flags & DC_EXEC) {
198  Goal *g = Goal::Get(goal);
199  g->progress = text;
200 
201  if (g->company == INVALID_COMPANY) {
203  } else {
205  }
206  }
207 
208  return CommandCost();
209 }
210 
219 {
220  if (_current_company != OWNER_DEITY) return CMD_ERROR;
221  if (!Goal::IsValidID(goal)) return CMD_ERROR;
222 
223  if (flags & DC_EXEC) {
224  Goal *g = Goal::Get(goal);
225  g->completed = completed;
226 
227  if (g->company == INVALID_COMPANY) {
229  } else {
231  }
232  }
233 
234  return CommandCost();
235 }
236 
248 CommandCost CmdGoalQuestion(DoCommandFlag flags, uint16_t uniqueid, uint32_t target, bool is_client, uint32_t button_mask, GoalQuestionType type, const std::string &text)
249 {
250  static_assert(sizeof(uint32_t) >= sizeof(CompanyID));
251  CompanyID company = (CompanyID)target;
252  static_assert(sizeof(uint32_t) >= sizeof(ClientID));
253  ClientID client = (ClientID)target;
254 
255  static_assert(GOAL_QUESTION_BUTTON_COUNT < 29);
256  button_mask &= (1U << GOAL_QUESTION_BUTTON_COUNT) - 1;
257 
258  if (_current_company != OWNER_DEITY) return CMD_ERROR;
259  if (text.empty()) return CMD_ERROR;
260  if (is_client) {
261  /* Only check during pre-flight; the client might have left between
262  * testing and executing. In that case it is fine to just ignore the
263  * fact the client is no longer here. */
264  if (!(flags & DC_EXEC) && _network_server && NetworkClientInfo::GetByClientID(client) == nullptr) return CMD_ERROR;
265  } else {
266  if (company != INVALID_COMPANY && !Company::IsValidID(company)) return CMD_ERROR;
267  }
268  uint min_buttons = (type == GQT_QUESTION ? 1 : 0);
269  if (CountBits(button_mask) < min_buttons || CountBits(button_mask) > 3) return CMD_ERROR;
270  if (type >= GQT_END) return CMD_ERROR;
271 
272  if (flags & DC_EXEC) {
273  if (is_client) {
274  if (client != _network_own_client_id) return CommandCost();
275  } else {
276  if (company == INVALID_COMPANY && !Company::IsValidID(_local_company)) return CommandCost();
277  if (company != INVALID_COMPANY && company != _local_company) return CommandCost();
278  }
279  ShowGoalQuestion(uniqueid, type, button_mask, text);
280  }
281 
282  return CommandCost();
283 }
284 
292 CommandCost CmdGoalQuestionAnswer(DoCommandFlag flags, uint16_t uniqueid, uint8_t button)
293 {
294  if (button >= GOAL_QUESTION_BUTTON_COUNT) return CMD_ERROR;
295 
296  if (_current_company == OWNER_DEITY) {
297  /* It has been requested to close this specific question on all clients */
298  if (flags & DC_EXEC) CloseWindowById(WC_GOAL_QUESTION, uniqueid);
299  return CommandCost();
300  }
301 
303  /* Somebody in the same company answered the question. Close the window */
304  if (flags & DC_EXEC) CloseWindowById(WC_GOAL_QUESTION, uniqueid);
305  if (!_network_server) return CommandCost();
306  }
307 
308  if (flags & DC_EXEC) {
309  Game::NewEvent(new ScriptEventGoalQuestionAnswer(uniqueid, (ScriptCompany::CompanyID)(uint8_t)_current_company, (ScriptGoal::QuestionButton)(1 << button)));
310  }
311 
312  return CommandCost();
313 }
game.hpp
OWNER_DEITY
@ OWNER_DEITY
The object is owned by a superuser / goal script.
Definition: company_type.h:27
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:3208
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:339
command_func.h
CMD_ERROR
static const CommandCost CMD_ERROR
Define a default return value for a failed command.
Definition: command_func.h:28
company_base.h
INVALID_COMPANY
@ INVALID_COMPANY
An invalid company.
Definition: company_type.h:30
_network_server
bool _network_server
network-server is active
Definition: network.cpp:66
CloseWindowById
void CloseWindowById(WindowClass cls, WindowNumber number, bool force, int data)
Close a window by its class and window number (if it is open).
Definition: window.cpp:1140
Owner
Owner
Enum for all companies/owners.
Definition: company_type.h:18
Pool::PoolItem::index
Tindex index
Index of this pool item.
Definition: pool_type.hpp:238
GT_TILE
@ GT_TILE
Destination is a tile.
Definition: goal_type.h:28
goal_base.h
town.h
GT_STORY_PAGE
@ GT_STORY_PAGE
Destination is a story page.
Definition: goal_type.h:32
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:290
CmdGoalQuestionAnswer
CommandCost CmdGoalQuestionAnswer(DoCommandFlag flags, uint16_t uniqueid, uint8_t button)
Reply to a goal question.
Definition: goal.cpp:292
DC_EXEC
@ DC_EXEC
execute the given command
Definition: command_type.h:376
DoCommandFlag
DoCommandFlag
List of flags for a command.
Definition: command_type.h:374
CmdRemoveGoal
CommandCost CmdRemoveGoal(DoCommandFlag flags, GoalID goal)
Remove a goal.
Definition: goal.cpp:114
network_base.h
NetworkClientInfo::GetByClientID
static NetworkClientInfo * GetByClientID(ClientID client_id)
Return the CI given it's client-identifier.
Definition: network.cpp:118
GT_COMPANY
@ GT_COMPANY
Destination is a company.
Definition: goal_type.h:31
CommandCost
Common return value for all commands.
Definition: command_type.h:23
GT_INDUSTRY
@ GT_INDUSTRY
Destination is an industry.
Definition: goal_type.h:29
Game::NewEvent
static void NewEvent(class ScriptEvent *event)
Queue a new event for a Game Script.
Definition: game_core.cpp:146
ShowGoalQuestion
void ShowGoalQuestion(uint16_t id, uint8_t type, uint32_t button_mask, const std::string &question)
Display a goal question.
Definition: goal_gui.cpp:482
_local_company
CompanyID _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
Definition: company_cmd.cpp:52
industry.h
safeguards.h
GoalTypeID
uint32_t GoalTypeID
Contains either tile, industry ID, town ID, company ID, or story page ID.
Definition: goal_type.h:35
_networking
bool _networking
are we in networking mode?
Definition: network.cpp:65
CmdSetGoalText
CommandCost CmdSetGoalText(DoCommandFlag flags, GoalID goal, const std::string &text)
Update goal text of a goal.
Definition: goal.cpp:165
stdafx.h
GoalID
uint16_t GoalID
ID of a goal.
Definition: goal_type.h:37
CmdSetGoalDestination
CommandCost CmdSetGoalDestination(DoCommandFlag flags, GoalID goal, GoalType type, GoalTypeID dest)
Update goal destination of a goal.
Definition: goal.cpp:143
CountBits
constexpr uint CountBits(T value)
Counts the number of set bits in a variable.
Definition: bitmath_func.hpp:262
IsValidTile
bool IsValidTile(Tile tile)
Checks if a tile is valid.
Definition: tile_map.h:161
_network_own_client_id
ClientID _network_own_client_id
Our client identifier.
Definition: network.cpp:70
CmdSetGoalCompleted
CommandCost CmdSetGoalCompleted(DoCommandFlag flags, GoalID goal, bool completed)
Update completed state of a goal.
Definition: goal.cpp:218
string_func.h
_current_company
CompanyID _current_company
Company currently doing an action.
Definition: company_cmd.cpp:53
Pool
Base class for all pools.
Definition: pool_type.hpp:80
Goal::progress
std::string progress
Progress text of the goal.
Definition: goal_base.h:26
ClientID
ClientID
'Unique' identifier to be given to clients
Definition: network_type.h:49
Pool::PoolItem<&_goal_pool >::GetNumItems
static size_t GetNumItems()
Returns number of valid items in the pool.
Definition: pool_type.hpp:369
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:3225
Goal::company
CompanyID company
Goal is for a specific company; INVALID_COMPANY if it is global.
Definition: goal_base.h:22
GT_NONE
@ GT_NONE
Destination is not linked.
Definition: goal_type.h:27
INVALID_GOAL
static const GoalID INVALID_GOAL
Constant representing a non-existing goal.
Definition: goal_type.h:39
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:137
goal_cmd.h
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:309
GT_TOWN
@ GT_TOWN
Destination is a town.
Definition: goal_type.h:30
GOAL_QUESTION_BUTTON_COUNT
static const uint32_t GOAL_QUESTION_BUTTON_COUNT
Amount of buttons available.
Definition: goal_type.h:15
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:237
network.h
window_func.h
CmdGoalQuestion
CommandCost CmdGoalQuestion(DoCommandFlag flags, uint16_t uniqueid, uint32_t target, bool is_client, uint32_t button_mask, GoalQuestionType type, const std::string &text)
Ask a goal related question.
Definition: goal.cpp:248
CmdSetGoalProgress
CommandCost CmdSetGoalProgress(DoCommandFlag flags, GoalID goal, const std::string &text)
Update progress text of a goal.
Definition: goal.cpp:192
Goal::text
std::string text
Text of the goal.
Definition: goal_base.h:25
CmdCreateGoal
std::tuple< CommandCost, GoalID > CmdCreateGoal(DoCommandFlag flags, CompanyID company, GoalType type, GoalTypeID dest, const std::string &text)
Create a new goal.
Definition: goal.cpp:78
gui.h
Pool::PoolItem<&_industry_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:328
pool_func.hpp
story_base.h
WC_MAIN_TOOLBAR
@ WC_MAIN_TOOLBAR
Main toolbar (the long bar at the top); Window numbers:
Definition: window_type.h:58
GoalType
GoalType
Types of goal destinations.
Definition: goal_type.h:26
Goal::type
GoalType type
Type of the goal.
Definition: goal_base.h:23
network_func.h