OpenTTD
goal.cpp
Go to the documentation of this file.
1 /* $Id$ */
2 
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  */
9 
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"
26 #include "network/network_base.h"
27 #include "network/network_func.h"
28 
29 #include "safeguards.h"
30 
31 
32 GoalID _new_goal_id;
33 
34 GoalPool _goal_pool("Goal");
36 
37 
48 CommandCost CmdCreateGoal(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
49 {
50  if (!Goal::CanAllocateItem()) return CMD_ERROR;
51 
52  GoalType type = (GoalType)GB(p1, 0, 8);
53  CompanyID company = (CompanyID)GB(p1, 8, 8);
54 
55  if (_current_company != OWNER_DEITY) return CMD_ERROR;
56  if (StrEmpty(text)) return CMD_ERROR;
57  if (company != INVALID_COMPANY && !Company::IsValidID(company)) return CMD_ERROR;
58 
59  switch (type) {
60  case GT_NONE:
61  if (p2 != 0) return CMD_ERROR;
62  break;
63 
64  case GT_TILE:
65  if (!IsValidTile(p2)) return CMD_ERROR;
66  break;
67 
68  case GT_INDUSTRY:
69  if (!Industry::IsValidID(p2)) return CMD_ERROR;
70  break;
71 
72  case GT_TOWN:
73  if (!Town::IsValidID(p2)) return CMD_ERROR;
74  break;
75 
76  case GT_COMPANY:
77  if (!Company::IsValidID(p2)) return CMD_ERROR;
78  break;
79 
80  case GT_STORY_PAGE: {
81  if (!StoryPage::IsValidID(p2)) return CMD_ERROR;
82  CompanyByte story_company = StoryPage::Get(p2)->company;
83  if (company == INVALID_COMPANY ? story_company != INVALID_COMPANY : story_company != INVALID_COMPANY && story_company != company) return CMD_ERROR;
84  break;
85  }
86 
87  default: return CMD_ERROR;
88  }
89 
90  if (flags & DC_EXEC) {
91  Goal *g = new Goal();
92  g->type = type;
93  g->dst = p2;
94  g->company = company;
95  g->text = stredup(text);
96  g->progress = NULL;
97  g->completed = false;
98 
99  if (g->company == INVALID_COMPANY) {
101  } else {
103  }
105 
106  _new_goal_id = g->index;
107  }
108 
109  return CommandCost();
110 }
111 
121 CommandCost CmdRemoveGoal(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
122 {
123  if (_current_company != OWNER_DEITY) return CMD_ERROR;
124  if (!Goal::IsValidID(p1)) return CMD_ERROR;
125 
126  if (flags & DC_EXEC) {
127  Goal *g = Goal::Get(p1);
128  CompanyID c = g->company;
129  delete g;
130 
131  if (c == INVALID_COMPANY) {
133  } else {
135  }
137  }
138 
139  return CommandCost();
140 }
141 
151 CommandCost CmdSetGoalText(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
152 {
153  if (_current_company != OWNER_DEITY) return CMD_ERROR;
154  if (!Goal::IsValidID(p1)) return CMD_ERROR;
155  if (StrEmpty(text)) return CMD_ERROR;
156 
157  if (flags & DC_EXEC) {
158  Goal *g = Goal::Get(p1);
159  free(g->text);
160  g->text = stredup(text);
161 
162  if (g->company == INVALID_COMPANY) {
164  } else {
166  }
167  }
168 
169  return CommandCost();
170 }
171 
181 CommandCost CmdSetGoalProgress(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
182 {
183  if (_current_company != OWNER_DEITY) return CMD_ERROR;
184  if (!Goal::IsValidID(p1)) return CMD_ERROR;
185 
186  if (flags & DC_EXEC) {
187  Goal *g = Goal::Get(p1);
188  free(g->progress);
189  if (StrEmpty(text)) {
190  g->progress = NULL;
191  } else {
192  g->progress = stredup(text);
193  }
194 
195  if (g->company == INVALID_COMPANY) {
197  } else {
199  }
200  }
201 
202  return CommandCost();
203 }
204 
214 CommandCost CmdSetGoalCompleted(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
215 {
216  if (_current_company != OWNER_DEITY) return CMD_ERROR;
217  if (!Goal::IsValidID(p1)) return CMD_ERROR;
218 
219  if (flags & DC_EXEC) {
220  Goal *g = Goal::Get(p1);
221  g->completed = p2 == 1;
222 
223  if (g->company == INVALID_COMPANY) {
225  } else {
227  }
228  }
229 
230  return CommandCost();
231 }
232 
247 CommandCost CmdGoalQuestion(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
248 {
249  uint16 uniqueid = (GoalType)GB(p1, 0, 16);
250  CompanyID company = (CompanyID)GB(p1, 16, 8);
251 #ifdef ENABLE_NETWORK
252  ClientID client = (ClientID)GB(p1, 16, 16);
253 #endif
254 
255  assert_compile(GOAL_QUESTION_BUTTON_COUNT < 29);
256  uint32 button_mask = GB(p2, 0, GOAL_QUESTION_BUTTON_COUNT);
257  byte type = GB(p2, 29, 2);
258  bool is_client = HasBit(p2, 31);
259 
260  if (_current_company != OWNER_DEITY) return CMD_ERROR;
261  if (StrEmpty(text)) return CMD_ERROR;
262  if (is_client) {
263 #ifdef ENABLE_NETWORK
264  if (NetworkClientInfo::GetByClientID(client) == nullptr) return CMD_ERROR;
265 #else
266  return CMD_ERROR;
267 #endif
268  } else {
269  if (company != INVALID_COMPANY && !Company::IsValidID(company)) return CMD_ERROR;
270  }
271  if (CountBits(button_mask) < 1 || CountBits(button_mask) > 3) return CMD_ERROR;
272  if (type >= GOAL_QUESTION_TYPE_COUNT) return CMD_ERROR;
273 
274  if (flags & DC_EXEC) {
275  if (is_client) {
276 #ifdef ENABLE_NETWORK
277  if (client != _network_own_client_id) return CommandCost();
278 #endif
279  } else {
280  if (company == INVALID_COMPANY && !Company::IsValidID(_local_company)) return CommandCost();
281  if (company != INVALID_COMPANY && company != _local_company) return CommandCost();
282  }
283  ShowGoalQuestion(uniqueid, type, button_mask, text);
284  }
285 
286  return CommandCost();
287 }
288 
298 CommandCost CmdGoalQuestionAnswer(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
299 {
300  if (p1 > UINT16_MAX) return CMD_ERROR;
301  if (p2 >= GOAL_QUESTION_BUTTON_COUNT) return CMD_ERROR;
302 
303  if (_current_company == OWNER_DEITY) {
304  /* It has been requested to close this specific question on all clients */
305  if (flags & DC_EXEC) DeleteWindowById(WC_GOAL_QUESTION, p1);
306  return CommandCost();
307  }
308 
310  /* Somebody in the same company answered the question. Close the window */
311  if (flags & DC_EXEC) DeleteWindowById(WC_GOAL_QUESTION, p1);
312  if (!_network_server) return CommandCost();
313  }
314 
315  if (flags & DC_EXEC) {
316  Game::NewEvent(new ScriptEventGoalQuestionAnswer(p1, (ScriptCompany::CompanyID)(byte)_current_company, (ScriptGoal::QuestionButton)(1 << p2)));
317  }
318 
319  return CommandCost();
320 }
static void NewEvent(class ScriptEvent *event)
Queue a new event for a Game Script.
Definition: game_core.cpp:143
Definition of stuff that is very close to a company, like the company struct itself.
bool _networking
are we in networking mode?
Definition: network.cpp:56
CommandCost CmdCreateGoal(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
Create a new goal.
Definition: goal.cpp:48
CommandCost CmdGoalQuestion(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
Ask a goal related question.
Definition: goal.cpp:247
Destination is a story page.
Definition: goal_type.h:27
static Titem * Get(size_t index)
Returns Titem with given index.
Definition: pool_type.hpp:246
Destination is a company.
Definition: goal_type.h:26
uint16 GoalID
ID of a goal.
Definition: goal_type.h:34
Popup with a set of buttons, designed to ask the user a question from a GameScript.
Definition: window_type.h:132
static const CommandCost CMD_ERROR
Define a default return value for a failed command.
Definition: command_func.h:25
Destination is a town.
Definition: goal_type.h:25
Destination is not linked.
Definition: goal_type.h:22
Struct about goals, current and completed.
Definition: goal_base.h:23
Goals list; Window numbers:
Definition: window_type.h:285
Tindex index
Index of this pool item.
Definition: pool_type.hpp:147
Base core network types and some helper functions to access them.
Common return value for all commands.
Definition: command_type.h:25
CompanyByte _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
Definition: company_cmd.cpp:46
GoalTypeID dst
Index of type.
Definition: goal_base.h:26
The object is owned by a superuser / goal script.
Definition: company_type.h:29
static bool IsValidTile(TileIndex tile)
Checks if a tile is valid.
Definition: tile_map.h:163
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:3319
Functions related to low-level strings.
Some methods of Pool are placed here in order to reduce compilation time and binary size...
CommandCost CmdSetGoalProgress(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
Update progress text of a goal.
Definition: goal.cpp:181
Destination is an industry.
Definition: goal_type.h:24
DoCommandFlag
List of flags for a command.
Definition: command_type.h:343
GoalType
Types of goal destinations.
Definition: goal_type.h:21
ClientID _network_own_client_id
Our client identifier.
Definition: network.cpp:63
Definition of base types and functions in a cross-platform compatible way.
A number of safeguards to prevent using unsafe methods.
char * stredup(const char *s, const char *last)
Create a duplicate of the given string.
Definition: string.cpp:138
Basic functions/variables used all over the place.
Destination is a tile.
Definition: goal_type.h:23
GoalTypeByte type
Type of the goal.
Definition: goal_base.h:25
Base class for all pools.
Definition: pool_type.hpp:83
#define INSTANTIATE_POOL_METHODS(name)
Force instantiation of pool methods so we don&#39;t get linker errors.
Definition: pool_func.hpp:226
void DeleteWindowById(WindowClass cls, WindowNumber number, bool force)
Delete a window by its class and window number (if it is open).
Definition: window.cpp:1146
execute the given command
Definition: command_type.h:345
Functions related to companies.
CompanyByte company
Goal is for a specific company; INVALID_COMPANY if it is global.
Definition: goal_base.h:24
char * progress
Progress text of the goal.
Definition: goal_base.h:28
static bool StrEmpty(const char *s)
Check if a string buffer is empty.
Definition: string_func.h:59
CompanyByte _current_company
Company currently doing an action.
Definition: company_cmd.cpp:47
uint32 TileIndex
The index/ID of a Tile.
Definition: tile_type.h:80
static size_t GetNumItems()
Returns number of valid items in the pool.
Definition: pool_type.hpp:276
ClientID
&#39;Unique&#39; identifier to be given to clients
Definition: network_type.h:43
bool completed
Is the goal completed or not?
Definition: goal_base.h:29
void ShowGoalQuestion(uint16 id, byte type, uint32 button_mask, const char *question)
Display a goal question.
Definition: goal_gui.cpp:489
static uint GB(const T x, const uint8 s, const uint8 n)
Fetch n bits from x, started at bit s.
CommandCost CmdRemoveGoal(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
Remove a goal.
Definition: goal.cpp:121
Goal base class.
static bool CanAllocateItem(size_t n=1)
Helper functions so we can use PoolItem::Function() instead of _poolitem_pool.Function() ...
Definition: pool_type.hpp:216
static uint CountBits(T value)
Counts the number of set bits in a variable.
Base functions for all Games.
Functions related to commands.
Network functions used by other parts of OpenTTD.
bool _network_server
network-server is active
Definition: network.cpp:57
Main toolbar (the long bar at the top); Window numbers:
Definition: window_type.h:53
static bool IsValidID(size_t index)
Tests whether given index can be used to get valid (non-NULL) Titem.
Definition: pool_type.hpp:235
CommandCost CmdSetGoalText(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
Update goal text of a goal.
Definition: goal.cpp:151
StoryPage base class.
Base of all industries.
static void free(const void *ptr)
Version of the standard free that accepts const pointers.
Definition: depend.cpp:114
static bool HasBit(const T x, const uint8 y)
Checks if a bit in a value is set.
static const uint32 GOAL_QUESTION_BUTTON_COUNT
Amount of buttons available.
Definition: goal_type.h:17
Base of the town class.
CommandCost CmdGoalQuestionAnswer(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
Reply to a goal question.
Definition: goal.cpp:298
char * text
Text of the goal.
Definition: goal_base.h:27
static const byte GOAL_QUESTION_TYPE_COUNT
Amount of question types.
Definition: goal_type.h:18
Owner
Enum for all companies/owners.
Definition: company_type.h:20
Window functions not directly related to making/drawing windows.
static NetworkClientInfo * GetByClientID(ClientID client_id)
Return the CI given it&#39;s client-identifier.
Definition: network.cpp:126
CommandCost CmdSetGoalCompleted(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
Update completed state of a goal.
Definition: goal.cpp:214
GUI functions that shouldn&#39;t be here.
An invalid company.
Definition: company_type.h:32
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:3301