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_story_page.cpp Implementation of ScriptStoryPage. */
10 #include "../../stdafx.h"
11 #include "script_story_page.hpp"
12 #include "script_error.hpp"
13 #include "script_industry.hpp"
14 #include "script_map.hpp"
15 #include "script_town.hpp"
16 #include "script_goal.hpp"
17 #include "../script_instance.hpp"
18 #include "../../story_base.h"
19 #include "../../goal_base.h"
20 #include "../../string_func.h"
21 #include "../../tile_map.h"
22 #include "../../story_cmd.h"
24 #include "../../safeguards.h"
26 static inline bool StoryPageElementTypeRequiresText(StoryPageElementType type
)
28 return type
== SPET_TEXT
|| type
== SPET_LOCATION
|| type
== SPET_BUTTON_PUSH
|| type
== SPET_BUTTON_TILE
|| type
== SPET_BUTTON_VEHICLE
;
31 /* static */ bool ScriptStoryPage::IsValidStoryPage(StoryPageID story_page_id
)
33 return ::StoryPage::IsValidID(story_page_id
);
36 /* static */ bool ScriptStoryPage::IsValidStoryPageElement(StoryPageElementID story_page_element_id
)
38 return ::StoryPageElement::IsValidID(story_page_element_id
);
41 /* static */ bool ScriptStoryPage::IsValidStoryPageElementType(StoryPageElementType type
)
43 return type
== SPET_TEXT
|| type
== SPET_LOCATION
|| type
== SPET_GOAL
|| type
== SPET_BUTTON_PUSH
|| type
== SPET_BUTTON_TILE
|| type
== SPET_BUTTON_VEHICLE
;
46 /* static */ ScriptStoryPage::StoryPageID
ScriptStoryPage::New(ScriptCompany::CompanyID company
, Text
*title
)
48 CCountedPtr
<Text
> counter(title
);
50 EnforceDeityMode(STORY_PAGE_INVALID
);
51 EnforcePrecondition(STORY_PAGE_INVALID
, company
== ScriptCompany::COMPANY_INVALID
|| ScriptCompany::ResolveCompanyID(company
) != ScriptCompany::COMPANY_INVALID
);
54 if (company
== ScriptCompany::COMPANY_INVALID
) c
= INVALID_COMPANY
;
56 if (!ScriptObject::Command
<CMD_CREATE_STORY_PAGE
>::Do(&ScriptInstance::DoCommandReturnStoryPageID
,
57 (::CompanyID
)c
, title
!= nullptr ? title
->GetEncodedText() : std::string
{})) return STORY_PAGE_INVALID
;
59 /* In case of test-mode, we return StoryPageID 0 */
60 return (ScriptStoryPage::StoryPageID
)0;
63 /* static */ ScriptStoryPage::StoryPageElementID
ScriptStoryPage::NewElement(StoryPageID story_page_id
, StoryPageElementType type
, SQInteger reference
, Text
*text
)
65 CCountedPtr
<Text
> counter(text
);
67 ::StoryPageElementType btype
= static_cast<::StoryPageElementType
>(type
);
69 EnforceDeityMode(STORY_PAGE_ELEMENT_INVALID
);
70 EnforcePrecondition(STORY_PAGE_ELEMENT_INVALID
, IsValidStoryPage(story_page_id
));
71 EnforcePrecondition(STORY_PAGE_ELEMENT_INVALID
, IsValidStoryPageElementType(type
));
72 std::string encoded_text
;
73 if (StoryPageElementTypeRequiresText(btype
)) {
74 EnforcePrecondition(STORY_PAGE_ELEMENT_INVALID
, text
!= nullptr);
75 encoded_text
= text
->GetEncodedText();
76 EnforcePreconditionEncodedText(STORY_PAGE_ELEMENT_INVALID
, encoded_text
);
78 EnforcePrecondition(STORY_PAGE_ELEMENT_INVALID
, type
!= SPET_LOCATION
|| ::IsValidTile((::TileIndex
)reference
));
79 EnforcePrecondition(STORY_PAGE_ELEMENT_INVALID
, type
!= SPET_GOAL
|| ScriptGoal::IsValidGoal((ScriptGoal::GoalID
)reference
));
80 EnforcePrecondition(STORY_PAGE_ELEMENT_INVALID
, type
!= SPET_GOAL
|| !(StoryPage::Get(story_page_id
)->company
== INVALID_COMPANY
&& Goal::Get(reference
)->company
!= INVALID_COMPANY
));
83 TileIndex reftile
= 0;
89 case SPET_BUTTON_PUSH
:
90 case SPET_BUTTON_TILE
:
91 case SPET_BUTTON_VEHICLE
:
100 if (!ScriptObject::Command
<CMD_CREATE_STORY_PAGE_ELEMENT
>::Do(&ScriptInstance::DoCommandReturnStoryPageElementID
,
102 (::StoryPageID
)story_page_id
, (::StoryPageElementType
)type
,
104 encoded_text
)) return STORY_PAGE_ELEMENT_INVALID
;
106 /* In case of test-mode, we return StoryPageElementID 0 */
107 return (ScriptStoryPage::StoryPageElementID
)0;
110 /* static */ bool ScriptStoryPage::UpdateElement(StoryPageElementID story_page_element_id
, SQInteger reference
, Text
*text
)
112 CCountedPtr
<Text
> counter(text
);
114 EnforceDeityMode(false);
115 EnforcePrecondition(false, IsValidStoryPageElement(story_page_element_id
));
117 const StoryPageElement
*pe
= StoryPageElement::Get(story_page_element_id
);
118 const StoryPage
*p
= StoryPage::Get(pe
->page
);
119 ::StoryPageElementType type
= pe
->type
;
121 std::string encoded_text
;
122 if (StoryPageElementTypeRequiresText(type
)) {
123 EnforcePrecondition(false, text
!= nullptr);
124 encoded_text
= text
->GetEncodedText();
125 EnforcePreconditionEncodedText(false, encoded_text
);
127 EnforcePrecondition(false, type
!= ::SPET_LOCATION
|| ::IsValidTile((::TileIndex
)reference
));
128 EnforcePrecondition(false, type
!= ::SPET_GOAL
|| ScriptGoal::IsValidGoal((ScriptGoal::GoalID
)reference
));
129 EnforcePrecondition(false, type
!= ::SPET_GOAL
|| !(p
->company
== INVALID_COMPANY
&& Goal::Get(reference
)->company
!= INVALID_COMPANY
));
132 TileIndex reftile
= 0;
134 case ::SPET_LOCATION
:
138 case ::SPET_BUTTON_PUSH
:
139 case ::SPET_BUTTON_TILE
:
140 case ::SPET_BUTTON_VEHICLE
:
149 return ScriptObject::Command
<CMD_UPDATE_STORY_PAGE_ELEMENT
>::Do(reftile
, story_page_element_id
, refid
, encoded_text
);
152 /* static */ SQInteger
ScriptStoryPage::GetPageSortValue(StoryPageID story_page_id
)
154 EnforcePrecondition(false, IsValidStoryPage(story_page_id
));
156 return StoryPage::Get(story_page_id
)->sort_value
;
159 /* static */ SQInteger
ScriptStoryPage::GetPageElementSortValue(StoryPageElementID story_page_element_id
)
161 EnforcePrecondition(false, IsValidStoryPageElement(story_page_element_id
));
163 return StoryPageElement::Get(story_page_element_id
)->sort_value
;
166 /* static */ bool ScriptStoryPage::SetTitle(StoryPageID story_page_id
, Text
*title
)
168 CCountedPtr
<Text
> counter(title
);
170 EnforcePrecondition(false, IsValidStoryPage(story_page_id
));
171 EnforceDeityMode(false);
173 return ScriptObject::Command
<CMD_SET_STORY_PAGE_TITLE
>::Do(story_page_id
, title
!= nullptr ? title
->GetEncodedText() : std::string
{});
176 /* static */ ScriptCompany::CompanyID
ScriptStoryPage::GetCompany(StoryPageID story_page_id
)
178 EnforcePrecondition(ScriptCompany::COMPANY_INVALID
, IsValidStoryPage(story_page_id
));
180 CompanyID c
= StoryPage::Get(story_page_id
)->company
;
181 ScriptCompany::CompanyID company
= c
== INVALID_COMPANY
? ScriptCompany::COMPANY_INVALID
: (ScriptCompany::CompanyID
)c
;
186 /* static */ ScriptDate::Date
ScriptStoryPage::GetDate(StoryPageID story_page_id
)
188 EnforcePrecondition(ScriptDate::DATE_INVALID
, IsValidStoryPage(story_page_id
));
189 EnforceDeityMode(ScriptDate::DATE_INVALID
);
191 return (ScriptDate::Date
)StoryPage::Get(story_page_id
)->date
.base();
194 /* static */ bool ScriptStoryPage::SetDate(StoryPageID story_page_id
, ScriptDate::Date date
)
196 EnforcePrecondition(false, IsValidStoryPage(story_page_id
));
197 EnforceDeityMode(false);
199 return ScriptObject::Command
<CMD_SET_STORY_PAGE_DATE
>::Do(story_page_id
, date
);
203 /* static */ bool ScriptStoryPage::Show(StoryPageID story_page_id
)
205 EnforcePrecondition(false, IsValidStoryPage(story_page_id
));
206 EnforceDeityMode(false);
208 return ScriptObject::Command
<CMD_SHOW_STORY_PAGE
>::Do(story_page_id
);
211 /* static */ bool ScriptStoryPage::Remove(StoryPageID story_page_id
)
213 EnforceDeityMode(false);
214 EnforcePrecondition(false, IsValidStoryPage(story_page_id
));
216 return ScriptObject::Command
<CMD_REMOVE_STORY_PAGE
>::Do(story_page_id
);
219 /* static */ bool ScriptStoryPage::RemoveElement(StoryPageElementID story_page_element_id
)
221 EnforceDeityMode(false);
222 EnforcePrecondition(false, IsValidStoryPageElement(story_page_element_id
));
224 return ScriptObject::Command
<CMD_REMOVE_STORY_PAGE_ELEMENT
>::Do(story_page_element_id
);
227 /* static */ bool ScriptStoryPage::IsValidStoryPageButtonColour(StoryPageButtonColour colour
)
229 return ::IsValidColours((::Colours
)colour
);
232 /* static */ bool ScriptStoryPage::IsValidStoryPageButtonFlags(StoryPageButtonFlags flags
)
234 /* Don't allow float left and right together */
235 if ((flags
& SPBF_FLOAT_LEFT
) && (flags
& SPBF_FLOAT_RIGHT
)) return false;
236 /* Don't allow undefined flags */
237 if (flags
& ~(SPBF_FLOAT_LEFT
| SPBF_FLOAT_RIGHT
)) return false;
241 /* static */ bool ScriptStoryPage::IsValidStoryPageButtonCursor(StoryPageButtonCursor cursor
)
243 return ::IsValidStoryPageButtonCursor((::StoryPageButtonCursor
)cursor
);
246 /* static */ ScriptStoryPage::StoryPageButtonFormatting
ScriptStoryPage::MakePushButtonReference(StoryPageButtonColour colour
, StoryPageButtonFlags flags
)
248 EnforcePrecondition(UINT32_MAX
, IsValidStoryPageButtonColour(colour
));
249 EnforcePrecondition(UINT32_MAX
, IsValidStoryPageButtonFlags(flags
));
251 StoryPageButtonData data
;
252 data
.SetColour((::Colours
)colour
);
253 data
.SetFlags((::StoryPageButtonFlags
)flags
);
254 if (!data
.ValidateColour()) return UINT32_MAX
;
255 if (!data
.ValidateFlags()) return UINT32_MAX
;
256 return data
.referenced_id
;
259 /* static */ ScriptStoryPage::StoryPageButtonFormatting
ScriptStoryPage::MakeTileButtonReference(StoryPageButtonColour colour
, StoryPageButtonFlags flags
, StoryPageButtonCursor cursor
)
261 EnforcePrecondition(UINT32_MAX
, IsValidStoryPageButtonColour(colour
));
262 EnforcePrecondition(UINT32_MAX
, IsValidStoryPageButtonFlags(flags
));
263 EnforcePrecondition(UINT32_MAX
, IsValidStoryPageButtonCursor(cursor
));
265 StoryPageButtonData data
;
266 data
.SetColour((::Colours
)colour
);
267 data
.SetFlags((::StoryPageButtonFlags
)flags
);
268 data
.SetCursor((::StoryPageButtonCursor
)cursor
);
269 if (!data
.ValidateColour()) return UINT32_MAX
;
270 if (!data
.ValidateFlags()) return UINT32_MAX
;
271 if (!data
.ValidateCursor()) return UINT32_MAX
;
272 return data
.referenced_id
;
275 /* static */ ScriptStoryPage::StoryPageButtonFormatting
ScriptStoryPage::MakeVehicleButtonReference(StoryPageButtonColour colour
, StoryPageButtonFlags flags
, StoryPageButtonCursor cursor
, ScriptVehicle::VehicleType vehtype
)
277 EnforcePrecondition(UINT32_MAX
, IsValidStoryPageButtonColour(colour
));
278 EnforcePrecondition(UINT32_MAX
, IsValidStoryPageButtonFlags(flags
));
279 EnforcePrecondition(UINT32_MAX
, IsValidStoryPageButtonCursor(cursor
));
280 EnforcePrecondition(UINT32_MAX
, vehtype
== ScriptVehicle::VT_INVALID
|| vehtype
== ScriptVehicle::VT_RAIL
|| vehtype
== ScriptVehicle::VT_ROAD
|| vehtype
== ScriptVehicle::VT_WATER
|| vehtype
== ScriptVehicle::VT_AIR
);
282 StoryPageButtonData data
;
283 data
.SetColour((::Colours
)colour
);
284 data
.SetFlags((::StoryPageButtonFlags
)flags
);
285 data
.SetCursor((::StoryPageButtonCursor
)cursor
);
286 data
.SetVehicleType((::VehicleType
)vehtype
);
287 if (!data
.ValidateColour()) return UINT32_MAX
;
288 if (!data
.ValidateFlags()) return UINT32_MAX
;
289 if (!data
.ValidateCursor()) return UINT32_MAX
;
290 if (!data
.ValidateVehicleType()) return UINT32_MAX
;
291 return data
.referenced_id
;