OpenTTD Source: src/goal.cpp Source File

OpenTTD Source 15.0-RC2

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 <https://www.gnu.org/licenses/old-licenses/gpl-2.0>.
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");
32 INSTANTIATE_POOL_METHODS(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 == CompanyID::Invalid() ? story_company != CompanyID::Invalid() : story_company != CompanyID::Invalid() && story_company != company) return false;
61 break;
62 }
63
64 default: return false;
65 }
66 return true;
67}
68
78std::tuple<CommandCost, GoalID> CmdCreateGoal(DoCommandFlags flags, CompanyID company, GoalType type, GoalTypeID dest, const EncodedString &text)
79{
80 if (!Goal::CanAllocateItem()) return { CMD_ERROR, GoalID::Invalid() };
81
82 if (_current_company != OWNER_DEITY) return { CMD_ERROR, GoalID::Invalid() };
83 if (text.empty()) return { CMD_ERROR, GoalID::Invalid() };
84 if (company != CompanyID::Invalid() && !Company::IsValidID(company)) return { CMD_ERROR, GoalID::Invalid() };
85 if (!Goal::IsValidGoalDestination(company, type, dest)) return { CMD_ERROR, GoalID::Invalid() };
86
87 if (flags.Test(DoCommandFlag::Execute)) {
88 Goal *g = new Goal(type, dest, company, text);
89
90 if (g->company == CompanyID::Invalid()) {
91 InvalidateWindowClassesData(WC_GOALS_LIST);
92 } else {
93 InvalidateWindowData(WC_GOALS_LIST, g->company);
94 }
95 if (Goal::GetNumItems() == 1) InvalidateWindowData(WC_MAIN_TOOLBAR, 0);
96
97 return { CommandCost(), g->index };
98 }
99
100 return { CommandCost(), GoalID::Invalid() };
101}
102
109 CommandCost CmdRemoveGoal(DoCommandFlags flags, GoalID goal)
110{
111 if (_current_company != OWNER_DEITY) return CMD_ERROR;
112 if (!Goal::IsValidID(goal)) return CMD_ERROR;
113
114 if (flags.Test(DoCommandFlag::Execute)) {
115 Goal *g = Goal::Get(goal);
116 CompanyID c = g->company;
117 delete g;
118
119 if (c == CompanyID::Invalid()) {
120 InvalidateWindowClassesData(WC_GOALS_LIST);
121 } else {
122 InvalidateWindowData(WC_GOALS_LIST, c);
123 }
124 if (Goal::GetNumItems() == 0) InvalidateWindowData(WC_MAIN_TOOLBAR, 0);
125 }
126
127 return CommandCost();
128}
129
138 CommandCost CmdSetGoalDestination(DoCommandFlags flags, GoalID goal, GoalType type, GoalTypeID dest)
139{
140 if (_current_company != OWNER_DEITY) return CMD_ERROR;
141 if (!Goal::IsValidID(goal)) return CMD_ERROR;
142 Goal *g = Goal::Get(goal);
143 if (!Goal::IsValidGoalDestination(g->company, type, dest)) return CMD_ERROR;
144
145 if (flags.Test(DoCommandFlag::Execute)) {
146 g->type = type;
147 g->dst = dest;
148 }
149
150 return CommandCost();
151}
152
160 CommandCost CmdSetGoalText(DoCommandFlags flags, GoalID goal, const EncodedString &text)
161{
162 if (_current_company != OWNER_DEITY) return CMD_ERROR;
163 if (!Goal::IsValidID(goal)) return CMD_ERROR;
164 if (text.empty()) return CMD_ERROR;
165
166 if (flags.Test(DoCommandFlag::Execute)) {
167 Goal *g = Goal::Get(goal);
168 g->text = text;
169
170 if (g->company == CompanyID::Invalid()) {
171 InvalidateWindowClassesData(WC_GOALS_LIST);
172 } else {
173 InvalidateWindowData(WC_GOALS_LIST, g->company);
174 }
175 }
176
177 return CommandCost();
178}
179
187 CommandCost CmdSetGoalProgress(DoCommandFlags flags, GoalID goal, const EncodedString &text)
188{
189 if (_current_company != OWNER_DEITY) return CMD_ERROR;
190 if (!Goal::IsValidID(goal)) return CMD_ERROR;
191
192 if (flags.Test(DoCommandFlag::Execute)) {
193 Goal *g = Goal::Get(goal);
194 g->progress = text;
195
196 if (g->company == CompanyID::Invalid()) {
197 InvalidateWindowClassesData(WC_GOALS_LIST);
198 } else {
199 InvalidateWindowData(WC_GOALS_LIST, g->company);
200 }
201 }
202
203 return CommandCost();
204}
205
213 CommandCost CmdSetGoalCompleted(DoCommandFlags flags, GoalID goal, bool completed)
214{
215 if (_current_company != OWNER_DEITY) return CMD_ERROR;
216 if (!Goal::IsValidID(goal)) return CMD_ERROR;
217
218 if (flags.Test(DoCommandFlag::Execute)) {
219 Goal *g = Goal::Get(goal);
220 g->completed = completed;
221
222 if (g->company == CompanyID::Invalid()) {
223 InvalidateWindowClassesData(WC_GOALS_LIST);
224 } else {
225 InvalidateWindowData(WC_GOALS_LIST, g->company);
226 }
227 }
228
229 return CommandCost();
230}
231
243 CommandCost CmdGoalQuestion(DoCommandFlags flags, uint16_t uniqueid, uint32_t target, bool is_client, uint32_t button_mask, GoalQuestionType type, const EncodedString &text)
244{
245 static_assert(sizeof(uint32_t) >= sizeof(CompanyID));
246 CompanyID company = (CompanyID)target;
247 static_assert(sizeof(uint32_t) >= sizeof(ClientID));
248 ClientID client = (ClientID)target;
249
250 static_assert(GOAL_QUESTION_BUTTON_COUNT < 29);
251 button_mask &= (1U << GOAL_QUESTION_BUTTON_COUNT) - 1;
252
253 if (_current_company != OWNER_DEITY) return CMD_ERROR;
254 if (text.empty()) return CMD_ERROR;
255 if (is_client) {
256 /* Only check during pre-flight; the client might have left between
257 * testing and executing. In that case it is fine to just ignore the
258 * fact the client is no longer here. */
259 if (!flags.Test(DoCommandFlag::Execute) && _network_server && NetworkClientInfo::GetByClientID(client) == nullptr) return CMD_ERROR;
260 } else {
261 if (company != CompanyID::Invalid() && !Company::IsValidID(company)) return CMD_ERROR;
262 }
263 uint min_buttons = (type == GQT_QUESTION ? 1 : 0);
264 if (CountBits(button_mask) < min_buttons || CountBits(button_mask) > 3) return CMD_ERROR;
265 if (type >= GQT_END) return CMD_ERROR;
266
267 if (flags.Test(DoCommandFlag::Execute)) {
268 if (is_client) {
269 if (client != _network_own_client_id) return CommandCost();
270 } else {
271 if (company == CompanyID::Invalid() && !Company::IsValidID(_local_company)) return CommandCost();
272 if (company != CompanyID::Invalid() && company != _local_company) return CommandCost();
273 }
274 ShowGoalQuestion(uniqueid, type, button_mask, text);
275 }
276
277 return CommandCost();
278}
279
287 CommandCost CmdGoalQuestionAnswer(DoCommandFlags flags, uint16_t uniqueid, uint8_t button)
288{
289 if (button >= GOAL_QUESTION_BUTTON_COUNT) return CMD_ERROR;
290
291 if (_current_company == OWNER_DEITY) {
292 /* It has been requested to close this specific question on all clients */
293 if (flags.Test(DoCommandFlag::Execute)) CloseWindowById(WC_GOAL_QUESTION, uniqueid);
294 return CommandCost();
295 }
296
297 if (_networking && _local_company == _current_company) {
298 /* Somebody in the same company answered the question. Close the window */
299 if (flags.Test(DoCommandFlag::Execute)) CloseWindowById(WC_GOAL_QUESTION, uniqueid);
300 if (!_network_server) return CommandCost();
301 }
302
303 if (flags.Test(DoCommandFlag::Execute)) {
304 Game::NewEvent(new ScriptEventGoalQuestionAnswer(uniqueid, _current_company, (ScriptGoal::QuestionButton)(1 << button)));
305 }
306
307 return CommandCost();
308}
CountBits
constexpr uint CountBits(T value)
Counts the number of set bits in a variable.
Definition bitmath_func.hpp:238
BaseBitSet::Test
constexpr bool Test(Tvalue_type value) const
Test if the value-th bit is set.
Definition base_bitset_type.hpp:141
CommandCost
Common return value for all commands.
Definition command_type.h:24
EncodedString
Container for an encoded string, created by GetEncodedString.
Definition strings_type.h:98
EnumBitSet
Enum-as-bit-set wrapper.
Definition enum_type.hpp:177
Game::NewEvent
static void NewEvent(class ScriptEvent *event)
Queue a new event for a Game Script.
Definition game_core.cpp:136
command_func.h
Functions related to commands.
CMD_ERROR
static const CommandCost CMD_ERROR
Define a default return value for a failed command.
Definition command_func.h:28
DoCommandFlag::Execute
@ Execute
execute the given command
company_base.h
Definition of stuff that is very close to a company, like the company struct itself.
_local_company
CompanyID _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
Definition company_cmd.cpp:55
_current_company
CompanyID _current_company
Company currently doing an action.
Definition company_cmd.cpp:56
company_func.h
Functions related to companies.
OWNER_DEITY
static constexpr Owner OWNER_DEITY
The object is owned by a superuser / goal script.
Definition company_type.h:28
game.hpp
Base functions for all Games.
CmdGoalQuestion
CommandCost CmdGoalQuestion(DoCommandFlags flags, uint16_t uniqueid, uint32_t target, bool is_client, uint32_t button_mask, GoalQuestionType type, const EncodedString &text)
Ask a goal related question.
Definition goal.cpp:243
CmdGoalQuestionAnswer
CommandCost CmdGoalQuestionAnswer(DoCommandFlags flags, uint16_t uniqueid, uint8_t button)
Reply to a goal question.
Definition goal.cpp:287
CmdSetGoalProgress
CommandCost CmdSetGoalProgress(DoCommandFlags flags, GoalID goal, const EncodedString &text)
Update progress text of a goal.
Definition goal.cpp:187
CmdRemoveGoal
CommandCost CmdRemoveGoal(DoCommandFlags flags, GoalID goal)
Remove a goal.
Definition goal.cpp:109
CmdCreateGoal
std::tuple< CommandCost, GoalID > CmdCreateGoal(DoCommandFlags flags, CompanyID company, GoalType type, GoalTypeID dest, const EncodedString &text)
Create a new goal.
Definition goal.cpp:78
CmdSetGoalText
CommandCost CmdSetGoalText(DoCommandFlags flags, GoalID goal, const EncodedString &text)
Update goal text of a goal.
Definition goal.cpp:160
CmdSetGoalDestination
CommandCost CmdSetGoalDestination(DoCommandFlags flags, GoalID goal, GoalType type, GoalTypeID dest)
Update goal destination of a goal.
Definition goal.cpp:138
CmdSetGoalCompleted
CommandCost CmdSetGoalCompleted(DoCommandFlags flags, GoalID goal, bool completed)
Update completed state of a goal.
Definition goal.cpp:213
goal_base.h
Goal base class.
goal_cmd.h
Command definitions related to goals.
ShowGoalQuestion
void ShowGoalQuestion(uint16_t id, uint8_t type, uint32_t button_mask, const EncodedString &question)
Display a goal question.
Definition goal_gui.cpp:475
GoalType
GoalType
Types of goal destinations.
Definition goal_type.h:26
GT_INDUSTRY
@ GT_INDUSTRY
Destination is an industry.
Definition goal_type.h:29
GT_STORY_PAGE
@ GT_STORY_PAGE
Destination is a story page.
Definition goal_type.h:32
GT_COMPANY
@ GT_COMPANY
Destination is a company.
Definition goal_type.h:31
GT_NONE
@ GT_NONE
Destination is not linked.
Definition goal_type.h:27
GT_TILE
@ GT_TILE
Destination is a tile.
Definition goal_type.h:28
GT_TOWN
@ GT_TOWN
Destination is a town.
Definition goal_type.h:30
GoalTypeID
uint32_t GoalTypeID
Contains either tile, industry ID, town ID, company ID, or story page ID.
Definition goal_type.h:35
GOAL_QUESTION_BUTTON_COUNT
static const uint32_t GOAL_QUESTION_BUTTON_COUNT
Amount of buttons available.
Definition goal_type.h:15
gui.h
GUI functions that shouldn't be here.
industry.h
Base of all industries.
_networking
bool _networking
are we in networking mode?
Definition network.cpp:66
_network_server
bool _network_server
network-server is active
Definition network.cpp:67
_network_own_client_id
ClientID _network_own_client_id
Our client identifier.
Definition network.cpp:71
network.h
Basic functions/variables used all over the place.
network_base.h
Base core network types and some helper functions to access them.
network_func.h
Network functions used by other parts of OpenTTD.
ClientID
ClientID
'Unique' identifier to be given to clients
Definition network_type.h:43
Invalid
@ Invalid
GRF is unusable with this version of OpenTTD.
Definition newgrf_config.h:28
pool_func.hpp
Some methods of Pool are placed here in order to reduce compilation time and binary size.
INSTANTIATE_POOL_METHODS
#define INSTANTIATE_POOL_METHODS(name)
Force instantiation of pool methods so we don't get linker errors.
Definition pool_func.hpp:210
safeguards.h
A number of safeguards to prevent using unsafe methods.
stdafx.h
Definition of base types and functions in a cross-platform compatible way.
story_base.h
StoryPage base class.
string_func.h
Functions related to low-level strings.
Goal
Struct about goals, current and completed.
Definition goal_base.h:22
Goal::progress
EncodedString progress
Progress text of the goal.
Definition goal_base.h:27
Goal::text
EncodedString text
Text of the goal.
Definition goal_base.h:26
Goal::completed
bool completed
Is the goal completed or not?
Definition goal_base.h:28
Goal::type
GoalType type
Type of the goal.
Definition goal_base.h:24
Goal::dst
GoalTypeID dst
Index of type.
Definition goal_base.h:25
Goal::company
CompanyID company
Goal is for a specific company; CompanyID::Invalid() if it is global.
Definition goal_base.h:23
NetworkClientInfo::GetByClientID
static NetworkClientInfo * GetByClientID(ClientID client_id)
Return the CI given it's client-identifier.
Definition network.cpp:117
PoolID< uint8_t, struct CompanyIDTag, 0xF, 0xFF >
Pool::PoolItem<&_story_page_pool >::Get
static Titem * Get(auto index)
Returns Titem with given index.
Definition pool_type.hpp:387
Pool::PoolItem<&_goal_pool >::GetNumItems
static size_t GetNumItems()
Returns number of valid items in the pool.
Definition pool_type.hpp:417
Pool::PoolItem::index
Tindex index
Index of this pool item.
Definition pool_type.hpp:286
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:357
Pool::PoolItem<&_industry_pool >::IsValidID
static bool IsValidID(auto index)
Tests whether given index can be used to get valid (non-nullptr) Titem.
Definition pool_type.hpp:376
Pool
Base class for all pools.
Definition pool_type.hpp:133
IsValidTile
bool IsValidTile(Tile tile)
Checks if a tile is valid.
Definition tile_map.h:161
town.h
Base of the town class.
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:1193
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:3294
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:3311
window_func.h
Window functions not directly related to making/drawing windows.
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:142
WC_GOALS_LIST
@ WC_GOALS_LIST
Goals list; Window numbers:
Definition window_type.h:295
WC_MAIN_TOOLBAR
@ WC_MAIN_TOOLBAR
Main toolbar (the long bar at the top); Window numbers:
Definition window_type.h:63