OpenTTD Source 20250312-master-gcdcc6b491d
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"
26#include "goal_cmd.h"
27
28#include "safeguards.h"
29
30
31GoalPool _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 == 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()) {
92 } else {
94 }
96
97 return { CommandCost(), g->index };
98 }
99
100 return { CommandCost(), GoalID::Invalid() };
101}
102
110{
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()) {
121 } else {
123 }
125 }
126
127 return CommandCost();
128}
129
139{
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
161{
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()) {
172 } else {
174 }
175 }
176
177 return CommandCost();
178}
179
188{
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()) {
198 } else {
200 }
201 }
202
203 return CommandCost();
204}
205
214{
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()) {
224 } else {
226 }
227 }
228
229 return CommandCost();
230}
231
243CommandCost 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
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
287CommandCost CmdGoalQuestionAnswer(DoCommandFlags flags, uint16_t uniqueid, uint8_t button)
288{
289 if (button >= GOAL_QUESTION_BUTTON_COUNT) return CMD_ERROR;
290
292 /* It has been requested to close this specific question on all clients */
294 return CommandCost();
295 }
296
298 /* Somebody in the same company answered the question. Close the window */
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}
constexpr uint CountBits(T value)
Counts the number of set bits in a variable.
constexpr bool Test(Tvalue_type value) const
Test if the value-th bit is set.
Common return value for all commands.
Container for an encoded string, created by GetEncodedString.
Enum-as-bit-set wrapper.
static void NewEvent(class ScriptEvent *event)
Queue a new event for a Game Script.
Functions related to commands.
static const CommandCost CMD_ERROR
Define a default return value for a failed command.
@ Execute
execute the given command
Definition of stuff that is very close to a company, like the company struct itself.
CompanyID _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
CompanyID _current_company
Company currently doing an action.
Functions related to companies.
static constexpr Owner OWNER_DEITY
The object is owned by a superuser / goal script.
Base functions for all Games.
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
CommandCost CmdGoalQuestionAnswer(DoCommandFlags flags, uint16_t uniqueid, uint8_t button)
Reply to a goal question.
Definition goal.cpp:287
CommandCost CmdSetGoalProgress(DoCommandFlags flags, GoalID goal, const EncodedString &text)
Update progress text of a goal.
Definition goal.cpp:187
CommandCost CmdRemoveGoal(DoCommandFlags flags, GoalID goal)
Remove a goal.
Definition goal.cpp:109
std::tuple< CommandCost, GoalID > CmdCreateGoal(DoCommandFlags flags, CompanyID company, GoalType type, GoalTypeID dest, const EncodedString &text)
Create a new goal.
Definition goal.cpp:78
CommandCost CmdSetGoalText(DoCommandFlags flags, GoalID goal, const EncodedString &text)
Update goal text of a goal.
Definition goal.cpp:160
CommandCost CmdSetGoalDestination(DoCommandFlags flags, GoalID goal, GoalType type, GoalTypeID dest)
Update goal destination of a goal.
Definition goal.cpp:138
CommandCost CmdSetGoalCompleted(DoCommandFlags flags, GoalID goal, bool completed)
Update completed state of a goal.
Definition goal.cpp:213
Goal base class.
Command definitions related to goals.
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
Types of goal destinations.
Definition goal_type.h:27
@ GT_INDUSTRY
Destination is an industry.
Definition goal_type.h:30
@ GT_STORY_PAGE
Destination is a story page.
Definition goal_type.h:33
@ GT_COMPANY
Destination is a company.
Definition goal_type.h:32
@ GT_NONE
Destination is not linked.
Definition goal_type.h:28
@ GT_TILE
Destination is a tile.
Definition goal_type.h:29
@ GT_TOWN
Destination is a town.
Definition goal_type.h:31
uint32_t GoalTypeID
Contains either tile, industry ID, town ID, company ID, or story page ID.
Definition goal_type.h:36
static const uint32_t GOAL_QUESTION_BUTTON_COUNT
Amount of buttons available.
Definition goal_type.h:16
GUI functions that shouldn't be here.
Base of all industries.
bool _networking
are we in networking mode?
Definition network.cpp:65
bool _network_server
network-server is active
Definition network.cpp:66
ClientID _network_own_client_id
Our client identifier.
Definition network.cpp:70
Basic functions/variables used all over the place.
Base core network types and some helper functions to access them.
Network functions used by other parts of OpenTTD.
ClientID
'Unique' identifier to be given to clients
@ Invalid
GRF is unusable with this version of OpenTTD.
Some methods of Pool are placed here in order to reduce compilation time and binary size.
#define INSTANTIATE_POOL_METHODS(name)
Force instantiation of pool methods so we don't get linker errors.
A number of safeguards to prevent using unsafe methods.
Definition of base types and functions in a cross-platform compatible way.
StoryPage base class.
Functions related to low-level strings.
Struct about goals, current and completed.
Definition goal_base.h:22
EncodedString progress
Progress text of the goal.
Definition goal_base.h:27
EncodedString text
Text of the goal.
Definition goal_base.h:26
bool completed
Is the goal completed or not?
Definition goal_base.h:28
GoalType type
Type of the goal.
Definition goal_base.h:24
GoalTypeID dst
Index of type.
Definition goal_base.h:25
CompanyID company
Goal is for a specific company; CompanyID::Invalid() if it is global.
Definition goal_base.h:23
static NetworkClientInfo * GetByClientID(ClientID client_id)
Return the CI given it's client-identifier.
Definition network.cpp:116
static Titem * Get(auto index)
Returns Titem with given index.
static size_t GetNumItems()
Returns number of valid items in the pool.
Tindex index
Index of this pool item.
static bool CanAllocateItem(size_t n=1)
Helper functions so we can use PoolItem::Function() instead of _poolitem_pool.Function()
static bool IsValidID(auto index)
Tests whether given index can be used to get valid (non-nullptr) Titem.
Base class for all pools.
bool IsValidTile(Tile tile)
Checks if a tile is valid.
Definition tile_map.h:161
Base of the town class.
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:1143
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:3224
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:3241
Window functions not directly related to making/drawing windows.
@ WC_GOAL_QUESTION
Popup with a set of buttons, designed to ask the user a question from a GameScript.
@ WC_GOALS_LIST
Goals list; Window numbers:
@ WC_MAIN_TOOLBAR
Main toolbar (the long bar at the top); Window numbers:
Definition window_type.h:60