diff options
author | zuu <zuu@openttd.org> | 2013-06-09 12:19:09 +0000 |
---|---|---|
committer | zuu <zuu@openttd.org> | 2013-06-09 12:19:09 +0000 |
commit | 9aa1bf026443ddc65ab4381e86c294943ddc30d8 (patch) | |
tree | 82af61f4b6f346bd71046a5d6fa6bab1f49b3d34 | |
parent | bea60988c67b40fb5b3058990779a4d572511224 (diff) | |
download | openttd-9aa1bf026443ddc65ab4381e86c294943ddc30d8.tar.xz |
(svn r25342) -Add: StoryPage data structures and GS API
-rw-r--r-- | projects/openttd_vs100.vcxproj | 6 | ||||
-rw-r--r-- | projects/openttd_vs100.vcxproj.filters | 18 | ||||
-rw-r--r-- | projects/openttd_vs80.vcproj | 24 | ||||
-rw-r--r-- | projects/openttd_vs90.vcproj | 24 | ||||
-rw-r--r-- | source.list | 6 | ||||
-rw-r--r-- | src/command.cpp | 10 | ||||
-rw-r--r-- | src/command_type.h | 5 | ||||
-rw-r--r-- | src/economy.cpp | 8 | ||||
-rw-r--r-- | src/game/game_instance.cpp | 2 | ||||
-rw-r--r-- | src/saveload/saveload.cpp | 2 | ||||
-rw-r--r-- | src/saveload/story_sl.cpp | 89 | ||||
-rw-r--r-- | src/script/api/game/game_story_page.hpp.sq | 39 | ||||
-rw-r--r-- | src/script/api/script_object.cpp | 22 | ||||
-rw-r--r-- | src/script/api/script_object.hpp | 22 | ||||
-rw-r--r-- | src/script/api/script_story_page.cpp | 119 | ||||
-rw-r--r-- | src/script/api/script_story_page.hpp | 142 | ||||
-rw-r--r-- | src/script/api/script_types.hpp | 2 | ||||
-rw-r--r-- | src/script/api/template/template_story_page.hpp.sq | 29 | ||||
-rw-r--r-- | src/script/script_instance.cpp | 10 | ||||
-rw-r--r-- | src/script/script_instance.hpp | 10 | ||||
-rw-r--r-- | src/script/script_storage.hpp | 3 | ||||
-rw-r--r-- | src/story.cpp | 271 | ||||
-rw-r--r-- | src/story_base.h | 85 | ||||
-rw-r--r-- | src/story_type.h | 28 |
24 files changed, 975 insertions, 1 deletions
diff --git a/projects/openttd_vs100.vcxproj b/projects/openttd_vs100.vcxproj index 0ce351cf2..1a772c6e8 100644 --- a/projects/openttd_vs100.vcxproj +++ b/projects/openttd_vs100.vcxproj @@ -366,6 +366,7 @@ <ClCompile Include="..\src\string.cpp" /> <ClCompile Include="..\src\stringfilter.cpp" /> <ClCompile Include="..\src\strings.cpp" /> + <ClCompile Include="..\src\story.cpp" /> <ClCompile Include="..\src\subsidy.cpp" /> <ClCompile Include="..\src\textbuf.cpp" /> <ClCompile Include="..\src\texteff.cpp" /> @@ -575,6 +576,8 @@ <ClInclude Include="..\src\station_type.h" /> <ClInclude Include="..\src\statusbar_gui.h" /> <ClInclude Include="..\src\stdafx.h" /> + <ClInclude Include="..\src\story_base.h" /> + <ClInclude Include="..\src\story_type.h" /> <ClInclude Include="..\src\strgen\strgen.h" /> <ClInclude Include="..\src\string_func.h" /> <ClInclude Include="..\src\string_type.h" /> @@ -833,6 +836,7 @@ <ClCompile Include="..\src\saveload\station_sl.cpp" /> <ClCompile Include="..\src\saveload\storage_sl.cpp" /> <ClCompile Include="..\src\saveload\strings_sl.cpp" /> + <ClCompile Include="..\src\saveload\story_sl.cpp" /> <ClCompile Include="..\src\saveload\subsidy_sl.cpp" /> <ClCompile Include="..\src\saveload\town_sl.cpp" /> <ClCompile Include="..\src\saveload\vehicle_sl.cpp" /> @@ -1005,6 +1009,7 @@ <ClInclude Include="..\src\script\api\script_signlist.hpp" /> <ClInclude Include="..\src\script\api\script_station.hpp" /> <ClInclude Include="..\src\script\api\script_stationlist.hpp" /> + <ClInclude Include="..\src\script\api\script_story_page.hpp" /> <ClInclude Include="..\src\script\api\script_subsidy.hpp" /> <ClInclude Include="..\src\script\api\script_subsidylist.hpp" /> <ClInclude Include="..\src\script\api\script_testmode.hpp" /> @@ -1066,6 +1071,7 @@ <ClCompile Include="..\src\script\api\script_signlist.cpp" /> <ClCompile Include="..\src\script\api\script_station.cpp" /> <ClCompile Include="..\src\script\api\script_stationlist.cpp" /> + <ClCompile Include="..\src\script\api\script_story_page.cpp" /> <ClCompile Include="..\src\script\api\script_subsidy.cpp" /> <ClCompile Include="..\src\script\api\script_subsidylist.cpp" /> <ClCompile Include="..\src\script\api\script_testmode.cpp" /> diff --git a/projects/openttd_vs100.vcxproj.filters b/projects/openttd_vs100.vcxproj.filters index 099ea2d3d..c521cc6d8 100644 --- a/projects/openttd_vs100.vcxproj.filters +++ b/projects/openttd_vs100.vcxproj.filters @@ -327,6 +327,9 @@ <ClCompile Include="..\src\strings.cpp"> <Filter>Source Files</Filter> </ClCompile> + <ClCompile Include="..\src\story.cpp"> + <Filter>Source Files</Filter> + </ClCompile> <ClCompile Include="..\src\subsidy.cpp"> <Filter>Source Files</Filter> </ClCompile> @@ -954,6 +957,12 @@ <ClInclude Include="..\src\stdafx.h"> <Filter>Header Files</Filter> </ClInclude> + <ClInclude Include="..\src\story_base.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\src\story_type.h"> + <Filter>Header Files</Filter> + </ClInclude> <ClInclude Include="..\src\strgen\strgen.h"> <Filter>Header Files</Filter> </ClInclude> @@ -1728,6 +1737,9 @@ <ClCompile Include="..\src\saveload\strings_sl.cpp"> <Filter>Save/Load handlers</Filter> </ClCompile> + <ClCompile Include="..\src\saveload\story_sl.cpp"> + <Filter>Save/Load handlers</Filter> + </ClCompile> <ClCompile Include="..\src\saveload\subsidy_sl.cpp"> <Filter>Save/Load handlers</Filter> </ClCompile> @@ -2244,6 +2256,9 @@ <ClInclude Include="..\src\script\api\script_stationlist.hpp"> <Filter>Script API</Filter> </ClInclude> + <ClInclude Include="..\src\script\api\script_story_page.hpp"> + <Filter>Script API</Filter> + </ClInclude> <ClInclude Include="..\src\script\api\script_subsidy.hpp"> <Filter>Script API</Filter> </ClInclude> @@ -2427,6 +2442,9 @@ <ClCompile Include="..\src\script\api\script_stationlist.cpp"> <Filter>Script API Implementation</Filter> </ClCompile> + <ClCompile Include="..\src\script\api\script_story_page.cpp"> + <Filter>Script API Implementation</Filter> + </ClCompile> <ClCompile Include="..\src\script\api\script_subsidy.cpp"> <Filter>Script API Implementation</Filter> </ClCompile> diff --git a/projects/openttd_vs80.vcproj b/projects/openttd_vs80.vcproj index 0ab3e9826..d6d806212 100644 --- a/projects/openttd_vs80.vcproj +++ b/projects/openttd_vs80.vcproj @@ -735,6 +735,10 @@ > </File> <File + RelativePath=".\..\src\story.cpp" + > + </File> + <File RelativePath=".\..\src\subsidy.cpp" > </File> @@ -1575,6 +1579,14 @@ > </File> <File + RelativePath=".\..\src\story_base.h" + > + </File> + <File + RelativePath=".\..\src\story_type.h" + > + </File> + <File RelativePath=".\..\src\strgen\strgen.h" > </File> @@ -2627,6 +2639,10 @@ > </File> <File + RelativePath=".\..\src\saveload\story_sl.cpp" + > + </File> + <File RelativePath=".\..\src\saveload\subsidy_sl.cpp" > </File> @@ -3355,6 +3371,10 @@ > </File> <File + RelativePath=".\..\src\script\api\script_story_page.hpp" + > + </File> + <File RelativePath=".\..\src\script\api\script_subsidy.hpp" > </File> @@ -3603,6 +3623,10 @@ > </File> <File + RelativePath=".\..\src\script\api\script_story_page.cpp" + > + </File> + <File RelativePath=".\..\src\script\api\script_subsidy.cpp" > </File> diff --git a/projects/openttd_vs90.vcproj b/projects/openttd_vs90.vcproj index 18d81566e..8219894e7 100644 --- a/projects/openttd_vs90.vcproj +++ b/projects/openttd_vs90.vcproj @@ -732,6 +732,10 @@ > </File> <File + RelativePath=".\..\src\story.cpp" + > + </File> + <File RelativePath=".\..\src\subsidy.cpp" > </File> @@ -1572,6 +1576,14 @@ > </File> <File + RelativePath=".\..\src\story_base.h" + > + </File> + <File + RelativePath=".\..\src\story_type.h" + > + </File> + <File RelativePath=".\..\src\strgen\strgen.h" > </File> @@ -2624,6 +2636,10 @@ > </File> <File + RelativePath=".\..\src\saveload\story_sl.cpp" + > + </File> + <File RelativePath=".\..\src\saveload\subsidy_sl.cpp" > </File> @@ -3352,6 +3368,10 @@ > </File> <File + RelativePath=".\..\src\script\api\script_story_page.hpp" + > + </File> + <File RelativePath=".\..\src\script\api\script_subsidy.hpp" > </File> @@ -3600,6 +3620,10 @@ > </File> <File + RelativePath=".\..\src\script\api\script_story_page.cpp" + > + </File> + <File RelativePath=".\..\src\script\api\script_subsidy.cpp" > </File> diff --git a/source.list b/source.list index 964debb52..1a72fbd8b 100644 --- a/source.list +++ b/source.list @@ -76,6 +76,7 @@ strgen/strgen_base.cpp string.cpp stringfilter.cpp strings.cpp +story.cpp subsidy.cpp textbuf.cpp texteff.cpp @@ -308,6 +309,8 @@ station_gui.h station_type.h statusbar_gui.h stdafx.h +story_base.h +story_type.h strgen/strgen.h string_func.h string_type.h @@ -591,6 +594,7 @@ saveload/signs_sl.cpp saveload/station_sl.cpp saveload/storage_sl.cpp saveload/strings_sl.cpp +saveload/story_sl.cpp saveload/subsidy_sl.cpp saveload/town_sl.cpp saveload/vehicle_sl.cpp @@ -783,6 +787,7 @@ script/api/script_sign.hpp script/api/script_signlist.hpp script/api/script_station.hpp script/api/script_stationlist.hpp +script/api/script_story_page.hpp script/api/script_subsidy.hpp script/api/script_subsidylist.hpp script/api/script_testmode.hpp @@ -846,6 +851,7 @@ script/api/script_sign.cpp script/api/script_signlist.cpp script/api/script_station.cpp script/api/script_stationlist.cpp +script/api/script_story_page.cpp script/api/script_subsidy.cpp script/api/script_subsidylist.cpp script/api/script_testmode.cpp diff --git a/src/command.cpp b/src/command.cpp index d49eb5cf6..38dc43521 100644 --- a/src/command.cpp +++ b/src/command.cpp @@ -155,6 +155,11 @@ CommandProc CmdSetGoalProgress; CommandProc CmdSetGoalCompleted; CommandProc CmdGoalQuestion; CommandProc CmdGoalQuestionAnswer; +CommandProc CmdCreateStoryPage; +CommandProc CmdCreateStoryPageElement; +CommandProc CmdUpdateStoryPageElement; +CommandProc CmdSetStoryPageTitle; +CommandProc CmdRemoveStoryPage; CommandProc CmdLevelLand; @@ -300,6 +305,11 @@ static const Command _command_proc_table[] = { DEF_CMD(CmdSetGoalCompleted, CMD_STR_CTRL | CMD_DEITY, CMDT_OTHER_MANAGEMENT ), // CMD_SET_GOAL_COMPLETED DEF_CMD(CmdGoalQuestion, CMD_STR_CTRL | CMD_DEITY, CMDT_OTHER_MANAGEMENT ), // CMD_GOAL_QUESTION DEF_CMD(CmdGoalQuestionAnswer, CMD_DEITY, CMDT_OTHER_MANAGEMENT ), // CMD_GOAL_QUESTION_ANSWER + DEF_CMD(CmdCreateStoryPage, CMD_STR_CTRL | CMD_DEITY, CMDT_OTHER_MANAGEMENT ), // CMD_CREATE_STORY_PAGE + DEF_CMD(CmdCreateStoryPageElement, CMD_STR_CTRL | CMD_DEITY, CMDT_OTHER_MANAGEMENT ), // CMD_CREATE_STORY_PAGE_ELEMENT + DEF_CMD(CmdUpdateStoryPageElement, CMD_STR_CTRL | CMD_DEITY, CMDT_OTHER_MANAGEMENT ), // CMD_UPDATE_STORY_PAGE_ELEMENT + DEF_CMD(CmdSetStoryPageTitle, CMD_STR_CTRL | CMD_DEITY, CMDT_OTHER_MANAGEMENT ), // CMD_SET_STORY_PAGE_TITLE + DEF_CMD(CmdRemoveStoryPage, CMD_STR_CTRL | CMD_DEITY, CMDT_OTHER_MANAGEMENT ), // CMD_REMOVE_STORY_PAGE DEF_CMD(CmdLevelLand, CMD_ALL_TILES | CMD_NO_TEST | CMD_AUTO, CMDT_LANDSCAPE_CONSTRUCTION), // CMD_LEVEL_LAND; test run might clear tiles multiple times, in execution that only happens once diff --git a/src/command_type.h b/src/command_type.h index 540421928..78e8c188e 100644 --- a/src/command_type.h +++ b/src/command_type.h @@ -271,6 +271,11 @@ enum Commands { CMD_SET_GOAL_COMPLETED, ///< update goal completed status of a goal CMD_GOAL_QUESTION, ///< ask a goal related question CMD_GOAL_QUESTION_ANSWER, ///< answer(s) to CMD_GOAL_QUESTION + CMD_CREATE_STORY_PAGE, ///< create a new story page + CMD_CREATE_STORY_PAGE_ELEMENT, ///< create a new story page element + CMD_UPDATE_STORY_PAGE_ELEMENT, ///< update a story page element + CMD_SET_STORY_PAGE_TITLE, ///< update title of a story page + CMD_REMOVE_STORY_PAGE, ///< remove a story page CMD_LEVEL_LAND, ///< level land CMD_BUILD_LOCK, ///< build a lock diff --git a/src/economy.cpp b/src/economy.cpp index 7ae5daccb..552839192 100644 --- a/src/economy.cpp +++ b/src/economy.cpp @@ -46,6 +46,7 @@ #include "game/game.hpp" #include "cargomonitor.h" #include "goal_base.h" +#include "story_base.h" #include "table/strings.h" #include "table/pricebase.h" @@ -509,7 +510,7 @@ void ChangeOwnershipOfCompanyItems(Owner old_owner, Owner new_owner) if (si->owner == old_owner) si->owner = new_owner == INVALID_OWNER ? OWNER_NONE : new_owner; } - /* Remove Game Script created Goals and CargoMonitors. */ + /* Remove Game Script created Goals, CargoMonitors and Story pages. */ Goal *g; FOR_ALL_GOALS(g) { if (g->company == old_owner) delete g; @@ -518,6 +519,11 @@ void ChangeOwnershipOfCompanyItems(Owner old_owner, Owner new_owner) ClearCargoPickupMonitoring(old_owner); ClearCargoDeliveryMonitoring(old_owner); + StoryPage *sp; + FOR_ALL_STORY_PAGES(sp) { + if (sp->company == old_owner) delete sp; + } + /* Change colour of existing windows */ if (new_owner != INVALID_OWNER) ChangeWindowOwner(old_owner, new_owner); diff --git a/src/game/game_instance.cpp b/src/game/game_instance.cpp index df52ca91a..bd588e039 100644 --- a/src/game/game_instance.cpp +++ b/src/game/game_instance.cpp @@ -66,6 +66,7 @@ #include "../script/api/game/game_signlist.hpp.sq" #include "../script/api/game/game_station.hpp.sq" #include "../script/api/game/game_stationlist.hpp.sq" +#include "../script/api/game/game_story_page.hpp.sq" #include "../script/api/game/game_subsidy.hpp.sq" #include "../script/api/game/game_subsidylist.hpp.sq" #include "../script/api/game/game_testmode.hpp.sq" @@ -169,6 +170,7 @@ void GameInstance::RegisterAPI() SQGSStation_Register(this->engine); SQGSStationList_Register(this->engine); SQGSStationList_Vehicle_Register(this->engine); + SQGSStoryPage_Register(this->engine); SQGSSubsidy_Register(this->engine); SQGSSubsidyList_Register(this->engine); SQGSTestMode_Register(this->engine); diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp index 9a18c33d9..1e7a2f0e0 100644 --- a/src/saveload/saveload.cpp +++ b/src/saveload/saveload.cpp @@ -419,6 +419,7 @@ extern const ChunkHandler _economy_chunk_handlers[]; extern const ChunkHandler _subsidy_chunk_handlers[]; extern const ChunkHandler _cargomonitor_chunk_handlers[]; extern const ChunkHandler _goal_chunk_handlers[]; +extern const ChunkHandler _story_page_chunk_handlers[]; extern const ChunkHandler _ai_chunk_handlers[]; extern const ChunkHandler _game_chunk_handlers[]; extern const ChunkHandler _animated_tile_chunk_handlers[]; @@ -449,6 +450,7 @@ static const ChunkHandler * const _chunk_handlers[] = { _subsidy_chunk_handlers, _cargomonitor_chunk_handlers, _goal_chunk_handlers, + _story_page_chunk_handlers, _engine_chunk_handlers, _town_chunk_handlers, _sign_chunk_handlers, diff --git a/src/saveload/story_sl.cpp b/src/saveload/story_sl.cpp new file mode 100644 index 000000000..fd2d142c2 --- /dev/null +++ b/src/saveload/story_sl.cpp @@ -0,0 +1,89 @@ +/* $Id$ */ + +/* + * This file is part of OpenTTD. + * 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. + * 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. + * 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/>. + */ + +/** @file story_page_sl.cpp Code handling saving and loading of story pages */ + +#include "../stdafx.h" +#include "../story_base.h" + +#include "saveload.h" + +static const SaveLoad _story_page_elements_desc[] = { + SLE_VAR(StoryPageElement, sort_value, SLE_UINT16), + SLE_VAR(StoryPageElement, page, SLE_UINT16), + SLE_VAR(StoryPageElement, type, SLE_UINT16), + SLE_VAR(StoryPageElement, referenced_id, SLE_UINT32), + SLE_STR(StoryPageElement, text, SLE_STR | SLF_ALLOW_CONTROL, 0), + SLE_END() +}; + +static void Save_STORY_PAGE_ELEMENT() +{ + StoryPageElement *s; + FOR_ALL_STORY_PAGE_ELEMENTS(s) { + SlSetArrayIndex(s->index); + SlObject(s, _story_page_elements_desc); + } +} + +static void Load_STORY_PAGE_ELEMENT() +{ + int index; + uint32 max_sort_value = 0; + while ((index = SlIterateArray()) != -1) { + StoryPageElement *s = new (index) StoryPageElement(); + SlObject(s, _story_page_elements_desc); + if (s->sort_value > max_sort_value) { + max_sort_value = s->sort_value; + } + } + /* Update the next sort value, so that the next + * created page is shown after all existing pages. + */ + _story_page_element_next_sort_value = max_sort_value + 1; +} + +static const SaveLoad _story_pages_desc[] = { + SLE_VAR(StoryPage, sort_value, SLE_UINT16), + SLE_VAR(StoryPage, date, SLE_UINT32), + SLE_VAR(StoryPage, company, SLE_UINT16), + SLE_STR(StoryPage, title, SLE_STR | SLF_ALLOW_CONTROL, 0), + SLE_END() +}; + +static void Save_STORY_PAGE() +{ + StoryPage *s; + FOR_ALL_STORY_PAGES(s) { + SlSetArrayIndex(s->index); + SlObject(s, _story_pages_desc); + } +} + +static void Load_STORY_PAGE() +{ + int index; + uint32 max_sort_value = 0; + while ((index = SlIterateArray()) != -1) { + StoryPage *s = new (index) StoryPage(); + SlObject(s, _story_pages_desc); + if (s->sort_value > max_sort_value) { + max_sort_value = s->sort_value; + } + } + /* Update the next sort value, so that the next + * created page is shown after all existing pages. + */ + _story_page_next_sort_value = max_sort_value + 1; +} + +extern const ChunkHandler _story_page_chunk_handlers[] = { + { 'STPE', Save_STORY_PAGE_ELEMENT, Load_STORY_PAGE_ELEMENT, NULL, NULL, CH_ARRAY}, + { 'STPA', Save_STORY_PAGE, Load_STORY_PAGE, NULL, NULL, CH_ARRAY | CH_LAST}, +}; diff --git a/src/script/api/game/game_story_page.hpp.sq b/src/script/api/game/game_story_page.hpp.sq new file mode 100644 index 000000000..abc9500d1 --- /dev/null +++ b/src/script/api/game/game_story_page.hpp.sq @@ -0,0 +1,39 @@ +/* $Id$ */ + +/* + * This file is part of OpenTTD. + * 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. + * 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. + * 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/>. + */ + +/* THIS FILE IS AUTO-GENERATED; PLEASE DO NOT ALTER MANUALLY */ + +#include "../script_story_page.hpp" +#include "../template/template_story_page.hpp.sq" + + +template <> const char *GetClassName<ScriptStoryPage, ST_GS>() { return "GSStoryPage"; } + +void SQGSStoryPage_Register(Squirrel *engine) +{ + DefSQClass<ScriptStoryPage, ST_GS> SQGSStoryPage("GSStoryPage"); + SQGSStoryPage.PreRegister(engine); + SQGSStoryPage.AddConstructor<void (ScriptStoryPage::*)(), 1>(engine, "x"); + + SQGSStoryPage.DefSQConst(engine, ScriptStoryPage::STORY_PAGE_INVALID, "STORY_PAGE_INVALID"); + SQGSStoryPage.DefSQConst(engine, ScriptStoryPage::STORY_PAGE_ELEMENT_INVALID, "STORY_PAGE_ELEMENT_INVALID"); + SQGSStoryPage.DefSQConst(engine, ScriptStoryPage::SPET_TEXT, "SPET_TEXT"); + SQGSStoryPage.DefSQConst(engine, ScriptStoryPage::SPET_LOCATION, "SPET_LOCATION"); + SQGSStoryPage.DefSQConst(engine, ScriptStoryPage::SPET_GOAL, "SPET_GOAL"); + + SQGSStoryPage.DefSQStaticMethod(engine, &ScriptStoryPage::IsValidStoryPage, "IsValidStoryPage", 2, ".i"); + SQGSStoryPage.DefSQStaticMethod(engine, &ScriptStoryPage::IsValidStoryPageElement, "IsValidStoryPageElement", 2, ".i"); + SQGSStoryPage.DefSQStaticMethod(engine, &ScriptStoryPage::New, "New", 3, ".i."); + SQGSStoryPage.DefSQStaticMethod(engine, &ScriptStoryPage::NewElement, "NewElement", 5, ".iii."); + SQGSStoryPage.DefSQStaticMethod(engine, &ScriptStoryPage::UpdateElement, "UpdateElement", 4, ".ii."); + SQGSStoryPage.DefSQStaticMethod(engine, &ScriptStoryPage::SetTitle, "SetTitle", 3, ".i."); + SQGSStoryPage.DefSQStaticMethod(engine, &ScriptStoryPage::Remove, "Remove", 2, ".i"); + + SQGSStoryPage.PostRegister(engine); +} diff --git a/src/script/api/script_object.cpp b/src/script/api/script_object.cpp index 2852c4ae9..6615b58de 100644 --- a/src/script/api/script_object.cpp +++ b/src/script/api/script_object.cpp @@ -144,6 +144,8 @@ ScriptObject::ActiveInstance::~ActiveInstance() SetNewSignID(_new_sign_id); SetNewGroupID(_new_group_id); SetNewGoalID(_new_goal_id); + SetNewStoryPageID(_new_story_page_id); + SetNewStoryPageElementID(_new_story_page_element_id); } /* static */ bool ScriptObject::GetLastCommandRes() @@ -191,6 +193,26 @@ ScriptObject::ActiveInstance::~ActiveInstance() return GetStorage()->new_goal_id; } +/* static */ void ScriptObject::SetNewStoryPageID(StoryPageID story_page_id) +{ + GetStorage()->new_story_page_id = story_page_id; +} + +/* static */ GroupID ScriptObject::GetNewStoryPageID() +{ + return GetStorage()->new_story_page_id; +} + +/* static */ void ScriptObject::SetNewStoryPageElementID(StoryPageElementID story_page_element_id) +{ + GetStorage()->new_story_page_element_id = story_page_element_id; +} + +/* static */ GroupID ScriptObject::GetNewStoryPageElementID() +{ + return GetStorage()->new_story_page_element_id; +} + /* static */ void ScriptObject::SetAllowDoCommand(bool allow) { GetStorage()->allow_do_command = allow; diff --git a/src/script/api/script_object.hpp b/src/script/api/script_object.hpp index a2631dd3d..482e76f66 100644 --- a/src/script/api/script_object.hpp +++ b/src/script/api/script_object.hpp @@ -167,6 +167,16 @@ protected: static GoalID GetNewGoalID(); /** + * Get the latest stored new_story_page_id. + */ + static StoryPageID GetNewStoryPageID(); + + /** + * Get the latest stored new_story_page_id. + */ + static StoryPageID GetNewStoryPageElementID(); + + /** * Store a allow_do_command per company. * @param allow The new allow. */ @@ -266,6 +276,18 @@ private: * @param goal_id The new GoalID. */ static void SetNewGoalID(GoalID goal_id); + + /** + * Store a new_story_page_id per company. + * @param story_page_id The new StoryPageID. + */ + static void SetNewStoryPageID(StoryPageID story_page_id); + + /** + * Store a new_story_page_id per company. + * @param story_page_id The new StoryPageID. + */ + static void SetNewStoryPageElementID(StoryPageElementID story_page_element_id); }; #endif /* SCRIPT_OBJECT_HPP */ diff --git a/src/script/api/script_story_page.cpp b/src/script/api/script_story_page.cpp new file mode 100644 index 000000000..e94bc0017 --- /dev/null +++ b/src/script/api/script_story_page.cpp @@ -0,0 +1,119 @@ +/* $Id$ */ + +/* + * This file is part of OpenTTD. + * 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. + * 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. + * 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/>. + */ + +/** @file script_story_page.cpp Implementation of ScriptStoryPage. */ + +#include "../../stdafx.h" +#include "script_story_page.hpp" +#include "script_error.hpp" +#include "script_industry.hpp" +#include "script_map.hpp" +#include "script_town.hpp" +#include "script_goal.hpp" +#include "../script_instance.hpp" +#include "../../story_base.h" +#include "../../goal_base.h" +#include "../../string_func.h" +#include "../../tile_map.h" + +/* static */ bool ScriptStoryPage::IsValidStoryPage(StoryPageID story_page_id) +{ + return ::StoryPage::IsValidID(story_page_id); +} + +/* static */ bool ScriptStoryPage::IsValidStoryPageElement(StoryPageElementID story_page_element_id) +{ + return ::StoryPageElement::IsValidID(story_page_element_id); +} + +/* static */ ScriptStoryPage::StoryPageID ScriptStoryPage::New(ScriptCompany::CompanyID company, Text *title) +{ + CCountedPtr<Text> counter(title); + + EnforcePrecondition(STORY_PAGE_INVALID, ScriptObject::GetCompany() == OWNER_DEITY); + EnforcePrecondition(STORY_PAGE_INVALID, company == ScriptCompany::COMPANY_INVALID || ScriptCompany::ResolveCompanyID(company) != ScriptCompany::COMPANY_INVALID); + + uint8 c = company; + if (company == ScriptCompany::COMPANY_INVALID) c = INVALID_COMPANY; + + if (!ScriptObject::DoCommand(0, + c, + 0, + CMD_CREATE_STORY_PAGE, + title != NULL? title->GetEncodedText() : NULL, + &ScriptInstance::DoCommandReturnStoryPageID)) return STORY_PAGE_INVALID; + + /* In case of test-mode, we return StoryPageID 0 */ + return (ScriptStoryPage::StoryPageID)0; +} + +/* static */ ScriptStoryPage::StoryPageElementID ScriptStoryPage::NewElement(StoryPageID story_page_id, StoryPageElementType type, uint32 reference, Text *text) +{ + CCountedPtr<Text> counter(text); + + EnforcePrecondition(STORY_PAGE_ELEMENT_INVALID, ScriptObject::GetCompany() == OWNER_DEITY); + EnforcePrecondition(STORY_PAGE_ELEMENT_INVALID, IsValidStoryPage(story_page_id)); + EnforcePrecondition(STORY_PAGE_ELEMENT_INVALID, (type != SPET_TEXT && type != SPET_LOCATION) || (text != NULL && !StrEmpty(text->GetEncodedText()))); + EnforcePrecondition(STORY_PAGE_ELEMENT_INVALID, type != SPET_LOCATION || ::IsValidTile(reference)); + EnforcePrecondition(STORY_PAGE_ELEMENT_INVALID, type != SPET_GOAL || ScriptGoal::IsValidGoal((ScriptGoal::GoalID)reference)); + EnforcePrecondition(STORY_PAGE_ELEMENT_INVALID, type != SPET_GOAL || !(StoryPage::Get(story_page_id)->company == INVALID_COMPANY && Goal::Get(reference)->company != INVALID_COMPANY)); + + if (!ScriptObject::DoCommand(type == SPET_LOCATION ? reference : 0, + story_page_id + (type << 16), + type == SPET_GOAL ? reference : 0, + CMD_CREATE_STORY_PAGE_ELEMENT, + type == SPET_TEXT || type == SPET_LOCATION ? text->GetEncodedText() : NULL, + &ScriptInstance::DoCommandReturnStoryPageElementID)) return STORY_PAGE_ELEMENT_INVALID; + + /* In case of test-mode, we return StoryPageElementID 0 */ + return (ScriptStoryPage::StoryPageElementID)0; +} + +/* static */ bool ScriptStoryPage::UpdateElement(StoryPageElementID story_page_element_id, uint32 reference, Text *text) +{ + CCountedPtr<Text> counter(text); + + EnforcePrecondition(false, ScriptObject::GetCompany() == OWNER_DEITY); + EnforcePrecondition(false, IsValidStoryPageElement(story_page_element_id)); + + StoryPageElement *pe = StoryPageElement::Get(story_page_element_id); + StoryPage *p = StoryPage::Get(pe->page); + ::StoryPageElementType type = pe->type; + + EnforcePrecondition(false, (type != SPET_TEXT && type != SPET_LOCATION) || (text != NULL && !StrEmpty(text->GetEncodedText()))); + EnforcePrecondition(false, type != SPET_LOCATION || ::IsValidTile(reference)); + EnforcePrecondition(false, type != SPET_GOAL || ScriptGoal::IsValidGoal((ScriptGoal::GoalID)reference)); + EnforcePrecondition(false, type != SPET_GOAL || !(p->company == INVALID_COMPANY && Goal::Get(reference)->company != INVALID_COMPANY)); + + return ScriptObject::DoCommand(type == SPET_LOCATION ? reference : 0, + pe->page, + type == SPET_GOAL ? reference : 0, + CMD_UPDATE_STORY_PAGE_ELEMENT, + type == SPET_TEXT || type == SPET_LOCATION ? text->GetEncodedText() : NULL, + &ScriptInstance::DoCommandReturnStoryPageElementID); +} + +/* static */ bool ScriptStoryPage::SetTitle(StoryPageID story_page_id, Text *title) +{ + CCountedPtr<Text> counter(title); + + EnforcePrecondition(false, IsValidStoryPage(story_page_id)); + EnforcePrecondition(false, ScriptObject::GetCompany() == OWNER_DEITY); + + return ScriptObject::DoCommand(0, story_page_id, 0, CMD_SET_STORY_PAGE_TITLE, title != NULL? title->GetEncodedText() : NULL); +} + +/* static */ bool ScriptStoryPage::Remove(StoryPageID story_page_id) +{ + EnforcePrecondition(false, ScriptObject::GetCompany() == OWNER_DEITY); + EnforcePrecondition(false, IsValidStoryPage(story_page_id)); + + return ScriptObject::DoCommand(0, story_page_id, 0, CMD_REMOVE_STORY_PAGE); +} + diff --git a/src/script/api/script_story_page.hpp b/src/script/api/script_story_page.hpp new file mode 100644 index 000000000..b013f2515 --- /dev/null +++ b/src/script/api/script_story_page.hpp @@ -0,0 +1,142 @@ +/* $Id$ */ + +/* + * This file is part of OpenTTD. + * 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. + * 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. + * 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/>. + */ + +/** @file script_story_page.hpp Everything to manipulate a story page. */ + +#ifndef SCRIPT_STORY_HPP +#define SCRIPT_STORY_HPP + +#include "script_company.hpp" +#include "../../story_type.h" +#include "../../story_base.h" + +/** + * Class that handles story page related functions. + * + * To create a page: + * 1. Create the page + * 2. Create page elements that will be appended to the page in the order which they are created. + * + * Pages can be either global or company specific. It is possible to mix, but the only mixed solution + * that will work is to have all global pages first. Once you create the first company specific page, + * it is not recommended to add additional global pages unless you clear up all pages first. + * + * Page elements are stacked vertically on a page. If goal elements are used, the element will + * become empty if the goal is removed while the page still exist. Instead of removing the goal, + * you can mark it as complete and the Story Book will show that the goal is completed. + * + * Mind that users might want to go back to old pages later on. Thus do not remove pages in + * the story book unless you really need to. + * + * @api game + */ +class ScriptStoryPage : public ScriptObject { +public: + /** + * The story page IDs. + */ + enum StoryPageID { + /* Note: these values represent part of the in-game StoryPageID enum */ + STORY_PAGE_INVALID = ::INVALID_STORY_PAGE, ///< An invalid story page id. + }; + + /** + * The story page element IDs. + */ + enum StoryPageElementID { + /* Note: these values represent part of the in-game StoryPageElementID enum */ + STORY_PAGE_ELEMENT_INVALID = ::INVALID_STORY_PAGE_ELEMENT, ///< An invalid story page element id. + }; + + /** + * Story page element types. + */ + enum StoryPageElementType { + SPET_TEXT = ::SPET_TEXT, ///< An element that displays a block of text. + SPET_LOCATION = ::SPET_LOCATION, ///< An element that displays a single line of text along with a button to view the referenced location. + SPET_GOAL = ::SPET_GOAL, ///< An element that displays a goal. + }; + + /** + * Check whether this is a valid story page ID. + * @param story_page_id The StoryPageID to check. + * @return True if and only if this story page is valid. + */ + static bool IsValidStoryPage(StoryPageID story_page_id); + + /** + * Check whether this is a valid story page element ID. + * @param story_page_element_id The StoryPageElementID to check. + * @return True if and only if this story page element is valid. + */ + static bool IsValidStoryPageElement(StoryPageElementID story_page_element_id); + + /** + * Create a new story page. + * @param company The company to create the story page for, or ScriptCompany::COMPANY_INVALID for all. + * @param title Page title (can be either a raw string, a ScriptText object, or null). + * @return The new StoryPageID, or STORY_INVALID if it failed. + * @pre No ScriptCompanyMode may be in scope. + * @pre company == COMPANY_INVALID || ResolveCompanyID(company) != COMPANY_INVALID. + */ + static StoryPageID New(ScriptCompany::CompanyID company, Text *title); + + /** + * Create a new story page element. + * @param story_page_id The page id of the story page which the page element should be appended to. + * @param type Which page element type to create. + * @param reference A reference value to the object that is refered to by some page element types. When type is SPET_GOAL, this is the goal ID. When type is SPET_LOCATION, this is the TileIndex. + * @param text The body text of page elements that allow custom text. (SPET_TEXT and SPET_LOCATION) + * @return The new StoryPageID, or STORY_INVALID if it failed. + * @pre No ScriptCompanyMode may be in scope. + * @pre IsValidStoryPage(story_page). + * @pre (type != SPET_TEXT && type != SPET_LOCATION) || (text != NULL && len(text) != 0). + * @pre type != SPET_LOCATION || ScriptMap::IsValidTile(reference). + * @pre type != SPET_GOAL || ScriptGoal::IsValidGoal(reference). + * @pre if type is SPET_GOAL and story_page is a global page, then referenced goal must be global. + */ + static StoryPageElementID NewElement(StoryPageID story_page_id, StoryPageElementType type, uint32 reference, Text *text); + + /** + * Update the content of a page element + * @param story_page_element_id The page id of the story page which the page element should be appended to. + * @param reference A reference value to the object that is refered to by some page element types. See also NewElement. + * @param text The body text of page elements that allow custom text. See also NewElement. + * @return The new StoryPageID, or STORY_INVALID if it failed. + * @pre No ScriptCompanyMode may be in scope. + * @pre IsValidStoryPage(story_page). + * @pre (type != SPET_TEXT && type != SPET_LOCATION) || (text != NULL && len(text) != 0). + * @pre type != SPET_LOCATION || ScriptMap::IsValidTile(reference). + * @pre type != SPET_GOAL || ScriptGoal::IsValidGoal(reference). + * @pre if type is SPET_GOAL and story_page is a global page, then referenced goal must be global. + */ + static bool UpdateElement(StoryPageElementID story_page_element_id, uint32 reference, Text *text); + + /** + * Update title of a story page. The title is shown in the page selector drop down. + * @param story_page_id The story page to update. + * @param title Page title (can be either a raw string, a ScriptText object, or null). + * @return True if the action succeeded. + * @pre No ScriptCompanyMode may be in scope. + * @pre IsValidStoryPage(story_page_id). + */ + static bool SetTitle(StoryPageID story_page_id, Text *title); + + /** + * Remove a story page from the list. + * @param story_page_id The story page to remove. + * @return True if the action succeeded. + * @pre No ScriptCompanyMode may be in scope. + * @pre IsValidStoryPage(story_page_id). + */ + static bool Remove(StoryPageID story_page_id); +}; + +#endif /* SCRIPT_STORY_HPP */ + diff --git a/src/script/api/script_types.hpp b/src/script/api/script_types.hpp index d4b72ea80..d3ac70b4d 100644 --- a/src/script/api/script_types.hpp +++ b/src/script/api/script_types.hpp @@ -100,6 +100,8 @@ typedef uint16 SignID; ///< The ID of a sign. typedef uint16 StationID; ///< The ID of a station. typedef uint16 StringID; ///< The ID of a string. typedef uint16 SubsidyID; ///< The ID of a subsidy. +typedef uint16 StoryPageID; ///< The ID of a story page. +typedef uint16 StoryPageElementID; ///< The ID of a story page element. typedef uint32 TileIndex; ///< The ID of a tile (just named differently). typedef uint16 TownID; ///< The ID of a town. typedef uint32 VehicleID; ///< The ID of a vehicle. diff --git a/src/script/api/template/template_story_page.hpp.sq b/src/script/api/template/template_story_page.hpp.sq new file mode 100644 index 000000000..4c322a3ac --- /dev/null +++ b/src/script/api/template/template_story_page.hpp.sq @@ -0,0 +1,29 @@ +/* $Id$ */ + +/* + * This file is part of OpenTTD. + * 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. + * 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. + * 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/>. + */ + +/* THIS FILE IS AUTO-GENERATED; PLEASE DO NOT ALTER MANUALLY */ + +#include "../script_story_page.hpp" + +namespace SQConvert { + /* Allow enums to be used as Squirrel parameters */ + template <> inline ScriptStoryPage::StoryPageID GetParam(ForceType<ScriptStoryPage::StoryPageID>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptStoryPage::StoryPageID)tmp; } + template <> inline int Return<ScriptStoryPage::StoryPageID>(HSQUIRRELVM vm, ScriptStoryPage::StoryPageID res) { sq_pushinteger(vm, (int32)res); return 1; } + template <> inline ScriptStoryPage::StoryPageElementID GetParam(ForceType<ScriptStoryPage::StoryPageElementID>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptStoryPage::StoryPageElementID)tmp; } + template <> inline int Return<ScriptStoryPage::StoryPageElementID>(HSQUIRRELVM vm, ScriptStoryPage::StoryPageElementID res) { sq_pushinteger(vm, (int32)res); return 1; } + template <> inline ScriptStoryPage::StoryPageElementType GetParam(ForceType<ScriptStoryPage::StoryPageElementType>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptStoryPage::StoryPageElementType)tmp; } + template <> inline int Return<ScriptStoryPage::StoryPageElementType>(HSQUIRRELVM vm, ScriptStoryPage::StoryPageElementType res) { sq_pushinteger(vm, (int32)res); return 1; } + + /* Allow ScriptStoryPage to be used as Squirrel parameter */ + template <> inline ScriptStoryPage *GetParam(ForceType<ScriptStoryPage *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (ScriptStoryPage *)instance; } + template <> inline ScriptStoryPage &GetParam(ForceType<ScriptStoryPage &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(ScriptStoryPage *)instance; } + template <> inline const ScriptStoryPage *GetParam(ForceType<const ScriptStoryPage *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (ScriptStoryPage *)instance; } + template <> inline const ScriptStoryPage &GetParam(ForceType<const ScriptStoryPage &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(ScriptStoryPage *)instance; } + template <> inline int Return<ScriptStoryPage *>(HSQUIRRELVM vm, ScriptStoryPage *res) { if (res == NULL) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, "StoryPage", res, NULL, DefSQDestructorCallback<ScriptStoryPage>, true); return 1; } +} // namespace SQConvert diff --git a/src/script/script_instance.cpp b/src/script/script_instance.cpp index 6a4471166..33a0c4d10 100644 --- a/src/script/script_instance.cpp +++ b/src/script/script_instance.cpp @@ -275,6 +275,16 @@ void ScriptInstance::CollectGarbage() const instance->engine->InsertResult(ScriptObject::GetNewGoalID()); } +/* static */ void ScriptInstance::DoCommandReturnStoryPageID(ScriptInstance *instance) +{ + instance->engine->InsertResult(ScriptObject::GetNewStoryPageID()); +} + +/* static */ void ScriptInstance::DoCommandReturnStoryPageElementID(ScriptInstance *instance) +{ + instance->engine->InsertResult(ScriptObject::GetNewStoryPageElementID()); +} + ScriptStorage *ScriptInstance::GetStorage() { return this->storage; diff --git a/src/script/script_instance.hpp b/src/script/script_instance.hpp index 2e7eb55cc..e6f3c64b2 100644 --- a/src/script/script_instance.hpp +++ b/src/script/script_instance.hpp @@ -108,6 +108,16 @@ public: static void DoCommandReturnGoalID(ScriptInstance *instance); /** + * Return a StoryPageID reply for a DoCommand. + */ + static void DoCommandReturnStoryPageID(ScriptInstance *instance); + + /** + * Return a StoryPageElementID reply for a DoCommand. + */ + static void DoCommandReturnStoryPageElementID(ScriptInstance *instance); + + /** * Get the controller attached to the instance. */ class ScriptController *GetController() { return controller; } diff --git a/src/script/script_storage.hpp b/src/script/script_storage.hpp index 79de2de8f..50e2b8dd5 100644 --- a/src/script/script_storage.hpp +++ b/src/script/script_storage.hpp @@ -17,6 +17,7 @@ #include "../road_type.h" #include "../group.h" #include "../goal_type.h" +#include "../story_type.h" #include "table/strings.h" #include <vector> @@ -49,6 +50,8 @@ private: SignID new_sign_id; ///< The ID of the new Sign. GroupID new_group_id; ///< The ID of the new Group. GoalID new_goal_id; ///< The ID of the new Goal. + StoryPageID new_story_page_id; ///< The ID of the new StoryPage. + StoryPageID new_story_page_element_id; ///< The ID of the new StoryPageElement. std::vector<int> callback_value; ///< The values which need to survive a callback. diff --git a/src/story.cpp b/src/story.cpp new file mode 100644 index 000000000..3574cf525 --- /dev/null +++ b/src/story.cpp @@ -0,0 +1,271 @@ +/* $Id$ */ + +/* + * This file is part of OpenTTD. + * 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. + * 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. + * 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/>. + */ + +/** @file story.cpp Handling of stories. */ + +#include "stdafx.h" +#include "story_base.h" +#include "core/pool_func.hpp" +#include "command_func.h" +#include "company_base.h" +#include "company_func.h" +#include "string_func.h" +#include "date_func.h" +#include "tile_map.h" +#include "goal_type.h" +#include "goal_base.h" + + +StoryPageElementID _new_story_page_element_id; +StoryPageID _new_story_page_id; +uint32 _story_page_element_next_sort_value; +uint32 _story_page_next_sort_value; + +StoryPageElementPool _story_page_element_pool("StoryPageElement"); +StoryPagePool _story_page_pool("StoryPage"); +INSTANTIATE_POOL_METHODS(StoryPageElement) +INSTANTIATE_POOL_METHODS(StoryPage) + +/** + * This helper for Create/Update PageElement Cmd procedure verifies if the page + * element parameters are correct for the given page element type. + * @param page_id The page id of the page which the page element (will) belong to + * @param type The type of the page element to create/update + * @param tile The tile parameter of the DoCommand proc + * @param reference The reference parameter of the DoCommand proc (p2) + * @param text The text parameter of the DoCommand proc + * @return true, if and only if the given parameters are valid for the given page elment type and page id. + */ +static bool VerifyElementContentParameters(uint32 page_id, StoryPageElementType type, TileIndex tile, uint32 reference, const char *text) +{ + switch (type) { + case SPET_TEXT: + if (StrEmpty(text)) return false; + break; + case SPET_LOCATION: + if (StrEmpty(text)) return false; + if (!IsValidTile(tile)) return false; + break; + case SPET_GOAL: + if (!Goal::IsValidID((GoalID)reference)) return false; + /* Reject company specific goals on global pages */ + if (StoryPage::Get(page_id)->company == INVALID_COMPANY && Goal::Get((GoalID)reference)->company != INVALID_COMPANY) return false; + break; + default: + return false; + } + + return true; +} + +/** + * This helper for Create/Update PageElement Cmd procedure updates a page + * element with new content data. + * @param pe The page element to update + * @param tile The tile parameter of the DoCommand proc + * @param reference The reference parameter of the DoCommand proc (p2) + * @param text The text parameter of the DoCommand proc + */ +static void UpdateElement(StoryPageElement &pe, TileIndex tile, uint32 reference, const char *text) +{ + switch (pe.type) { + case SPET_TEXT: + pe.text = strdup(text); + break; + case SPET_LOCATION: + pe.text = strdup(text); + pe.referenced_id = tile; + break; + case SPET_GOAL: + pe.referenced_id = (GoalID)reference; + break; + } +} + +/** + * Create a new story page. + * @param tile unused. + * @param flags type of operation + * @param p1 various bitstuffed elements + * - p1 = (bit 0 - 7) - Company for which this story page belongs to. + * @param p2 unused. + * @param text Title of the story page. Null is allowed in wich case a generic page title is provided by OpenTTD. + * @return the cost of this operation or an error + */ +CommandCost CmdCreateStoryPage(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +{ + if (!StoryPage::CanAllocateItem()) return CMD_ERROR; + + CompanyID company = (CompanyID)GB(p1, 0, 8); + + if (_current_company != OWNER_DEITY) return CMD_ERROR; + if (company != INVALID_COMPANY && !Company::IsValidID(company)) return CMD_ERROR; + + if (flags & DC_EXEC) { + if (_story_page_pool.items == 0) { + /* Initialize the next sort value variable. */ + _story_page_next_sort_value = 0; + } + + StoryPage *s = new StoryPage(); + s->sort_value = _story_page_next_sort_value; + s->date = _date; + s->company = company; + if (StrEmpty(text)) { + s->title = NULL; + } else { + s->title = strdup(text); + } + + _new_story_page_id = s->index; + _story_page_next_sort_value++; + } + + return CommandCost(); +} + +/** + * Create a new story page element. + * @param tile Tile location if it is a location page element, otherwise unused. + * @param flags type of operation + * @param p1 various bitstuffed elements + * - p1 = (bit 0 - 15) - The page which the element belongs to. + * (bit 16 - 31) - Page element type + * @param p2 Id of referenced object + * @param text Text content in case it is a text or location page element + * @return the cost of this operation or an error + */ +CommandCost CmdCreateStoryPageElement(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +{ + if (!StoryPageElement::CanAllocateItem()) return CMD_ERROR; + + StoryPageID page_id = (CompanyID)GB(p1, 0, 16); + StoryPageElementType type = (StoryPageElementType) GB(p1, 16, 16); + + /* Allow at most 128 elements per page. */ + uint16 element_count = 0; + StoryPageElement *iter; + FOR_ALL_STORY_PAGE_ELEMENTS(iter) { + if (iter->page == page_id) element_count++; + } + if (element_count >= 128) return CMD_ERROR; + + if (_current_company != OWNER_DEITY) return CMD_ERROR; + if (!StoryPage::IsValidID(page_id)) return CMD_ERROR; + if (!VerifyElementContentParameters(page_id, type, tile, p2, text)) return CMD_ERROR; + + if (flags & DC_EXEC) { + if (_story_page_element_pool.items == 0) { + /* Initialize the next sort value variable. */ + _story_page_element_next_sort_value = 0; + } + + StoryPageElement *pe = new StoryPageElement(); + pe->sort_value = _story_page_element_next_sort_value; + pe->type = type; + pe->page = page_id; + UpdateElement(*pe, tile, p2, text); + + _new_story_page_element_id = pe->index; + _story_page_element_next_sort_value++; + } + + return CommandCost(); +} + +/** + * Update a new story page element. + * @param tile Tile location if it is a location page element, otherwise unused. + * @param flags type of operation + * @param p1 various bitstuffed elements + * - p1 = (bit 0 - 15) - The page element to update. + * (bit 16 - 31) - unused + * @param p2 Id of referenced object + * @param text Text content in case it is a text or location page element + * @return the cost of this operation or an error + */ +CommandCost CmdUpdateStoryPageElement(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +{ + StoryPageElementID page_element_id = (StoryPageElementID)GB(p1, 0, 16); + + if (_current_company != OWNER_DEITY) return CMD_ERROR; + if (!StoryPageElement::IsValidID(page_element_id)) return CMD_ERROR; + + StoryPageElement *pe = StoryPageElement::Get(page_element_id); + StoryPageID page_id = pe->page; + StoryPageElementType type = pe->type; + + if (!VerifyElementContentParameters(page_id, type, tile, p2, text)) return CMD_ERROR; + + if (flags & DC_EXEC) { + UpdateElement(*pe, tile, p2, text); + } + + return CommandCost(); +} + +/** + * Update title of a story page. + * @param tile unused. + * @param flags type of operation + * @param p1 StoryPageID to update. + * @param p2 unused + * @param text title text of the story page. + * @return the cost of this operation or an error + */ +CommandCost CmdSetStoryPageTitle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +{ + if (_current_company != OWNER_DEITY) return CMD_ERROR; + StoryPageID page_id = (StoryPageID)p1; + if (!StoryPage::IsValidID(page_id)) return CMD_ERROR; + + if (flags & DC_EXEC) { + StoryPage *p = StoryPage::Get(page_id); + free(p->title); + if (StrEmpty(text)) { + p->title = NULL; + } else { + p->title = strdup(text); + } + } + + return CommandCost(); +} + +/** + * Remove a story page and associated story page elements. + * @param tile unused. + * @param flags type of operation + * @param p1 StoryPageID to remove. + * @param p2 unused. + * @param text unused. + * @return the cost of this operation or an error + */ +CommandCost CmdRemoveStoryPage(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +{ + if (_current_company != OWNER_DEITY) return CMD_ERROR; + StoryPageID page_id = (StoryPageID)p1; + if (!StoryPage::IsValidID(page_id)) return CMD_ERROR; + + if (flags & DC_EXEC) { + StoryPage *p = StoryPage::Get(page_id); + + StoryPageElement *pe; + FOR_ALL_STORY_PAGE_ELEMENTS(pe) { + if (pe->page == p->index) { + delete pe; + } + } + + delete p; + } + + return CommandCost(); +} + diff --git a/src/story_base.h b/src/story_base.h new file mode 100644 index 000000000..edb89db7a --- /dev/null +++ b/src/story_base.h @@ -0,0 +1,85 @@ +/* $Id$ */ + +/* + * This file is part of OpenTTD. + * 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. + * 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. + * 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/>. + */ + +/** @file story_base.h %StoryPage base class. */ + +#ifndef STORY_BASE_H +#define STORY_BASE_H + +#include "company_type.h" +#include "story_type.h" +#include "date_type.h" +#include "core/pool_type.hpp" + +typedef Pool<StoryPageElement, StoryPageElementID, 64, 64000> StoryPageElementPool; +typedef Pool<StoryPage, StoryPageID, 64, 64000> StoryPagePool; +extern StoryPageElementPool _story_page_element_pool; +extern StoryPagePool _story_page_pool; +extern uint32 _story_page_element_next_sort_value; +extern uint32 _story_page_next_sort_value; + +/* + * Each story page element is one of these types. + */ +enum StoryPageElementType { + SPET_TEXT, ///< A text element. + SPET_LOCATION, ///< An element that references a tile along with a one-line text. + SPET_GOAL, ///< An element that references a goal. +}; + +/** + * Struct about story page elements. + * Each StoryPage is composed of one or more page elements that provide + * page content. Each element only contain one type of content. + **/ +struct StoryPageElement : StoryPageElementPool::PoolItem<&_story_page_element_pool> { + uint32 sort_value; ///< A number that increases for every created story page element. Used for sorting. The id of a story page element is the pool index. + uint16 page; ///< Id of the page which the page element belongs to + StoryPageElementType type; ///< Type of page element + + uint32 referenced_id; ///< Id of referenced object (location, goal etc.) + char *text; ///< Static content text of page element + + /** + * We need an (empty) constructor so struct isn't zeroed (as C++ standard states) + */ + inline StoryPageElement() { } + + /** + * (Empty) destructor has to be defined else operator delete might be called with NULL parameter + */ + inline ~StoryPageElement() { free(this->text); } +}; + +/** Struct about stories, current and completed */ +struct StoryPage : StoryPagePool::PoolItem<&_story_page_pool> { + uint32 sort_value; ///< A number that increases for every created story page. Used for sorting. The id of a story page is the pool index. + Date date; ///< Date when the page was created. + CompanyByte company; ///< StoryPage is for a specific company; INVALID_COMPANY if it is global + + char *title; ///< Title of story page + + /** + * We need an (empty) constructor so struct isn't zeroed (as C++ standard states) + */ + inline StoryPage() { } + + /** + * (Empty) destructor has to be defined else operator delete might be called with NULL parameter + */ + inline ~StoryPage() { free(this->title); } +}; + +#define FOR_ALL_STORY_PAGE_ELEMENTS_FROM(var, start) FOR_ALL_ITEMS_FROM(StoryPageElement, story_page_element_index, var, start) +#define FOR_ALL_STORY_PAGE_ELEMENTS(var) FOR_ALL_STORY_PAGE_ELEMENTS_FROM(var, 0) +#define FOR_ALL_STORY_PAGES_FROM(var, start) FOR_ALL_ITEMS_FROM(StoryPage, story_page_index, var, start) +#define FOR_ALL_STORY_PAGES(var) FOR_ALL_STORY_PAGES_FROM(var, 0) + +#endif /* STORY_BASE_H */ + diff --git a/src/story_type.h b/src/story_type.h new file mode 100644 index 000000000..392249da2 --- /dev/null +++ b/src/story_type.h @@ -0,0 +1,28 @@ +/* $Id$ */ + +/* + * This file is part of OpenTTD. + * 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. + * 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. + * 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/>. + */ + +/** @file story_type.h basic types related to story pages */ + +#ifndef STORY_TYPE_H +#define STORY_TYPE_H + +#include "core/enum_type.hpp" + +typedef uint16 StoryPageElementID; ///< ID of a story page element +typedef uint16 StoryPageID; ///< ID of a story page +struct StoryPageElement; +struct StoryPage; + +extern StoryPageElementID _new_story_page_element_id; +extern StoryPageID _new_story_page_id; +static const StoryPageElementID INVALID_STORY_PAGE_ELEMENT = 0xFFFF; ///< Constant representing a non-existing story page element. +static const StoryPageID INVALID_STORY_PAGE = 0xFFFF; ///< Constant representing a non-existing story page. + +#endif /* STORY_TYPE_H */ + |