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/>.
8 /** @file script_goal.cpp Implementation of ScriptGoal. */
10 #include "../../stdafx.h"
11 #include "script_game.hpp"
12 #include "script_goal.hpp"
13 #include "script_error.hpp"
14 #include "script_industry.hpp"
15 #include "script_map.hpp"
16 #include "script_town.hpp"
17 #include "script_story_page.hpp"
18 #include "../script_instance.hpp"
19 #include "../../goal_base.h"
20 #include "../../string_func.h"
21 #include "../../network/network_base.h"
22 #include "../../goal_cmd.h"
24 #include "../../safeguards.h"
26 /* static */ bool ScriptGoal::IsValidGoal(GoalID goal_id
)
28 return ::Goal::IsValidID(goal_id
);
31 /* static */ bool ScriptGoal::IsValidGoalDestination(ScriptCompany::CompanyID company
, GoalType type
, SQInteger destination
)
33 CompanyID c
= (::CompanyID
)company
;
34 if (company
== ScriptCompany::COMPANY_INVALID
) c
= INVALID_COMPANY
;
35 StoryPage
*story_page
= nullptr;
36 if (type
== GT_STORY_PAGE
&& ScriptStoryPage::IsValidStoryPage((ScriptStoryPage::StoryPageID
)destination
)) story_page
= ::StoryPage::Get((ScriptStoryPage::StoryPageID
)destination
);
37 return (type
== GT_NONE
&& destination
== 0) ||
38 (type
== GT_TILE
&& ScriptMap::IsValidTile(destination
)) ||
39 (type
== GT_INDUSTRY
&& ScriptIndustry::IsValidIndustry(destination
)) ||
40 (type
== GT_TOWN
&& ScriptTown::IsValidTown(destination
)) ||
41 (type
== GT_COMPANY
&& ScriptCompany::ResolveCompanyID((ScriptCompany::CompanyID
)destination
) != ScriptCompany::COMPANY_INVALID
) ||
42 (type
== GT_STORY_PAGE
&& story_page
!= nullptr && (c
== INVALID_COMPANY
? story_page
->company
== INVALID_COMPANY
: story_page
->company
== INVALID_COMPANY
|| story_page
->company
== c
));
45 /* static */ ScriptGoal::GoalID
ScriptGoal::New(ScriptCompany::CompanyID company
, Text
*goal
, GoalType type
, SQInteger destination
)
47 CCountedPtr
<Text
> counter(goal
);
49 EnforceDeityMode(GOAL_INVALID
);
50 EnforcePrecondition(GOAL_INVALID
, goal
!= nullptr);
51 std::string text
= goal
->GetEncodedText();
52 EnforcePreconditionEncodedText(GOAL_INVALID
, text
);
53 EnforcePrecondition(GOAL_INVALID
, company
== ScriptCompany::COMPANY_INVALID
|| ScriptCompany::ResolveCompanyID(company
) != ScriptCompany::COMPANY_INVALID
);
54 EnforcePrecondition(GOAL_INVALID
, IsValidGoalDestination(company
, type
, destination
));
56 if (!ScriptObject::Command
<CMD_CREATE_GOAL
>::Do(&ScriptInstance::DoCommandReturnGoalID
, (::CompanyID
)company
, (::GoalType
)type
, destination
, text
)) return GOAL_INVALID
;
58 /* In case of test-mode, we return GoalID 0 */
59 return (ScriptGoal::GoalID
)0;
62 /* static */ bool ScriptGoal::Remove(GoalID goal_id
)
64 EnforceDeityMode(false);
65 EnforcePrecondition(false, IsValidGoal(goal_id
));
67 return ScriptObject::Command
<CMD_REMOVE_GOAL
>::Do(goal_id
);
70 /* static */ bool ScriptGoal::SetDestination(GoalID goal_id
, GoalType type
, SQInteger destination
)
72 EnforceDeityMode(false);
73 EnforcePrecondition(false, IsValidGoal(goal_id
));
74 const Goal
*g
= Goal::Get(goal_id
);
75 EnforcePrecondition(false, IsValidGoalDestination((ScriptCompany::CompanyID
)g
->company
, type
, destination
));
77 return ScriptObject::Command
<CMD_SET_GOAL_DESTINATION
>::Do(goal_id
, (::GoalType
)type
, destination
);
80 /* static */ bool ScriptGoal::SetText(GoalID goal_id
, Text
*goal
)
82 CCountedPtr
<Text
> counter(goal
);
84 EnforcePrecondition(false, IsValidGoal(goal_id
));
85 EnforceDeityMode(false);
86 EnforcePrecondition(false, goal
!= nullptr);
87 std::string text
= goal
->GetEncodedText();
88 EnforcePreconditionEncodedText(false, text
);
90 return ScriptObject::Command
<CMD_SET_GOAL_TEXT
>::Do(goal_id
, text
);
93 /* static */ bool ScriptGoal::SetProgress(GoalID goal_id
, Text
*progress
)
95 CCountedPtr
<Text
> counter(progress
);
97 EnforcePrecondition(false, IsValidGoal(goal_id
));
98 EnforceDeityMode(false);
100 return ScriptObject::Command
<CMD_SET_GOAL_PROGRESS
>::Do(goal_id
, progress
!= nullptr ? progress
->GetEncodedText() : std::string
{});
103 /* static */ bool ScriptGoal::SetCompleted(GoalID goal_id
, bool completed
)
105 EnforcePrecondition(false, IsValidGoal(goal_id
));
106 EnforceDeityMode(false);
108 return ScriptObject::Command
<CMD_SET_GOAL_COMPLETED
>::Do(goal_id
, completed
);
111 /* static */ bool ScriptGoal::IsCompleted(GoalID goal_id
)
113 EnforcePrecondition(false, IsValidGoal(goal_id
));
114 EnforceDeityMode(false);
116 const Goal
*g
= Goal::Get(goal_id
);
117 return g
!= nullptr && g
->completed
;
120 /* static */ bool ScriptGoal::DoQuestion(SQInteger uniqueid
, uint32_t target
, bool is_client
, Text
*question
, QuestionType type
, SQInteger buttons
)
122 CCountedPtr
<Text
> counter(question
);
124 EnforceDeityMode(false);
125 EnforcePrecondition(false, question
!= nullptr);
126 std::string text
= question
->GetEncodedText();
127 EnforcePreconditionEncodedText(false, text
);
128 uint min_buttons
= (type
== QT_QUESTION
? 1 : 0);
129 EnforcePrecondition(false, CountBits
<uint64_t>(buttons
) >= min_buttons
&& CountBits
<uint64_t>(buttons
) <= 3);
130 EnforcePrecondition(false, buttons
>= 0 && buttons
< (1 << ::GOAL_QUESTION_BUTTON_COUNT
));
131 EnforcePrecondition(false, (int)type
< ::GQT_END
);
132 EnforcePrecondition(false, uniqueid
>= 0 && uniqueid
<= UINT16_MAX
);
134 return ScriptObject::Command
<CMD_GOAL_QUESTION
>::Do(uniqueid
, target
, is_client
, buttons
, (::GoalQuestionType
)type
, text
);
137 /* static */ bool ScriptGoal::Question(SQInteger uniqueid
, ScriptCompany::CompanyID company
, Text
*question
, QuestionType type
, SQInteger buttons
)
139 EnforcePrecondition(false, company
== ScriptCompany::COMPANY_INVALID
|| ScriptCompany::ResolveCompanyID(company
) != ScriptCompany::COMPANY_INVALID
);
141 if (company
== ScriptCompany::COMPANY_INVALID
) c
= INVALID_COMPANY
;
143 return DoQuestion(uniqueid
, c
, false, question
, type
, buttons
);
146 /* static */ bool ScriptGoal::QuestionClient(SQInteger uniqueid
, ScriptClient::ClientID client
, Text
*question
, QuestionType type
, SQInteger buttons
)
148 EnforcePrecondition(false, ScriptGame::IsMultiplayer());
149 EnforcePrecondition(false, ScriptClient::ResolveClientID(client
) != ScriptClient::CLIENT_INVALID
);
150 return DoQuestion(uniqueid
, client
, true, question
, type
, buttons
);
153 /* static */ bool ScriptGoal::CloseQuestion(SQInteger uniqueid
)
155 EnforceDeityMode(false);
156 EnforcePrecondition(false, uniqueid
>= 0 && uniqueid
<= UINT16_MAX
);
158 return ScriptObject::Command
<CMD_GOAL_QUESTION_ANSWER
>::Do(uniqueid
, 0);