summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/command.cpp4
-rw-r--r--src/command_type.h2
-rw-r--r--src/game/game_instance.cpp2
-rw-r--r--src/goal.cpp120
-rw-r--r--src/goal_base.h44
-rw-r--r--src/goal_gui.cpp253
-rw-r--r--src/goal_type.h33
-rw-r--r--src/gui.h1
-rw-r--r--src/lang/english.txt9
-rw-r--r--src/saveload/goal_sl.cpp45
-rw-r--r--src/saveload/saveload.cpp2
-rw-r--r--src/script/api/game/game_goal.hpp.sq36
-rw-r--r--src/script/api/script_goal.cpp51
-rw-r--r--src/script/api/script_goal.hpp73
-rw-r--r--src/script/api/script_object.cpp12
-rw-r--r--src/script/api/script_object.hpp11
-rw-r--r--src/script/api/script_types.hpp5
-rw-r--r--src/script/api/template/template_goal.hpp.sq27
-rw-r--r--src/script/script_instance.cpp5
-rw-r--r--src/script/script_instance.hpp5
-rw-r--r--src/script/script_storage.hpp2
-rw-r--r--src/toolbar_gui.cpp7
-rw-r--r--src/widgets/goal_widget.h22
-rw-r--r--src/window_type.h6
24 files changed, 775 insertions, 2 deletions
diff --git a/src/command.cpp b/src/command.cpp
index b34538294..47d305021 100644
--- a/src/command.cpp
+++ b/src/command.cpp
@@ -150,6 +150,8 @@ CommandProc CmdBuildLock;
CommandProc CmdCreateSubsidy;
CommandProc CmdCompanyCtrl;
CommandProc CmdCustomNewsItem;
+CommandProc CmdCreateGoal;
+CommandProc CmdRemoveGoal;
CommandProc CmdLevelLand;
@@ -286,6 +288,8 @@ static const Command _command_proc_table[] = {
DEF_CMD(CmdCreateSubsidy, CMD_DEITY, CMDT_OTHER_MANAGEMENT ), // CMD_CREATE_SUBSIDY
DEF_CMD(CmdCompanyCtrl, CMD_SPECTATOR | CMD_CLIENT_ID, CMDT_SERVER_SETTING ), // CMD_COMPANY_CTRL
DEF_CMD(CmdCustomNewsItem, CMD_DEITY, CMDT_OTHER_MANAGEMENT ), // CMD_CUSTOM_NEWS_ITEM
+ DEF_CMD(CmdCreateGoal, CMD_DEITY, CMDT_OTHER_MANAGEMENT ), // CMD_CREATE_GOAL
+ DEF_CMD(CmdRemoveGoal, CMD_DEITY, CMDT_OTHER_MANAGEMENT ), // CMD_REMOVE_GOAL
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 eb1db573e..2e50c5eae 100644
--- a/src/command_type.h
+++ b/src/command_type.h
@@ -264,6 +264,8 @@ enum Commands {
CMD_CREATE_SUBSIDY, ///< create a new subsidy
CMD_COMPANY_CTRL, ///< used in multiplayer to create a new companies etc.
CMD_CUSTOM_NEWS_ITEM, ///< create a custom news message
+ CMD_CREATE_GOAL, ///< create a new goal
+ CMD_REMOVE_GOAL, ///< remove a goal
CMD_LEVEL_LAND, ///< level land
CMD_BUILD_LOCK, ///< build a lock
diff --git a/src/game/game_instance.cpp b/src/game/game_instance.cpp
index 438ccc019..ffe9a2db5 100644
--- a/src/game/game_instance.cpp
+++ b/src/game/game_instance.cpp
@@ -44,6 +44,7 @@
#include "../script/api/game/game_execmode.hpp.sq"
#include "../script/api/game/game_game.hpp.sq"
#include "../script/api/game/game_gamesettings.hpp.sq"
+#include "../script/api/game/game_goal.hpp.sq"
#include "../script/api/game/game_industry.hpp.sq"
#include "../script/api/game/game_industrylist.hpp.sq"
#include "../script/api/game/game_industrytype.hpp.sq"
@@ -132,6 +133,7 @@ void GameInstance::RegisterAPI()
SQGSExecMode_Register(this->engine);
SQGSGame_Register(this->engine);
SQGSGameSettings_Register(this->engine);
+ SQGSGoal_Register(this->engine);
SQGSIndustry_Register(this->engine);
SQGSIndustryList_Register(this->engine);
SQGSIndustryList_CargoAccepting_Register(this->engine);
diff --git a/src/goal.cpp b/src/goal.cpp
new file mode 100644
index 000000000..91ba6d288
--- /dev/null
+++ b/src/goal.cpp
@@ -0,0 +1,120 @@
+/* $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 goal.cpp Handling of goals. */
+
+#include "stdafx.h"
+#include "company_func.h"
+#include "industry.h"
+#include "town.h"
+#include "news_func.h"
+#include "ai/ai.hpp"
+#include "station_base.h"
+#include "cargotype.h"
+#include "strings_func.h"
+#include "window_func.h"
+#include "goal_base.h"
+#include "core/pool_func.hpp"
+#include "core/random_func.hpp"
+#include "game/game.hpp"
+#include "command_func.h"
+#include "company_base.h"
+#include "string_func.h"
+
+#include "table/strings.h"
+
+GoalID _new_goal_id;
+
+GoalPool _goal_pool("Goal");
+INSTANTIATE_POOL_METHODS(Goal)
+
+/**
+ * Create a new goal.
+ * @param tile unused.
+ * @param flags type of operation
+ * @param p1 various bitstuffed elements
+ * - p1 = (bit 0 - 7) - GoalType of destination.
+ * - p1 = (bit 8 - 15) - Company for which this goal is.
+ * @param p2 GoalTypeID of destination.
+ * @param text Text of the goal.
+ * @return the cost of this operation or an error
+ */
+CommandCost CmdCreateGoal(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
+{
+ if (!Goal::CanAllocateItem()) return CMD_ERROR;
+
+ GoalType type = (GoalType)GB(p1, 0, 8);
+ CompanyID company = (CompanyID)GB(p1, 8, 8);
+
+ if (_current_company != OWNER_DEITY) return CMD_ERROR;
+ if (StrEmpty(text)) return CMD_ERROR;
+ if (company != INVALID_COMPANY && !Company::IsValidID(company)) return CMD_ERROR;
+
+ switch (type) {
+ case GT_NONE:
+ if (p2 != 0) return CMD_ERROR;
+ break;
+
+ case GT_TILE:
+ if (!IsValidTile(p2)) return CMD_ERROR;
+ break;
+
+ case GT_INDUSTRY:
+ if (!Industry::IsValidID(p2)) return CMD_ERROR;
+ break;
+
+ case GT_TOWN:
+ if (!Town::IsValidID(p2)) return CMD_ERROR;
+ break;
+
+ case GT_COMPANY:
+ if (!Company::IsValidID(p2)) return CMD_ERROR;
+ break;
+
+ default: return CMD_ERROR;
+ }
+
+ if (flags & DC_EXEC) {
+ Goal *g = new Goal();
+ g->type = type;
+ g->dst = p2;
+ g->company = company;
+ g->text = strdup(text);
+
+ InvalidateWindowData(WC_GOALS_LIST, 0);
+
+ _new_goal_id = g->index;
+ }
+
+ return CommandCost();
+}
+
+/**
+ * Remove a goal.
+ * @param tile unused.
+ * @param flags type of operation
+ * @param p1 GoalID to remove.
+ * @param p2 unused.
+ * @param text unused.
+ * @return the cost of this operation or an error
+ */
+CommandCost CmdRemoveGoal(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
+{
+ if (_current_company != OWNER_DEITY) return CMD_ERROR;
+ if (!Goal::IsValidID(p1)) return CMD_ERROR;
+
+ if (flags & DC_EXEC) {
+ Goal *g = Goal::Get(p1);
+ delete g;
+
+ InvalidateWindowData(WC_GOALS_LIST, 0);
+ }
+
+ return CommandCost();
+}
diff --git a/src/goal_base.h b/src/goal_base.h
new file mode 100644
index 000000000..7b789abde
--- /dev/null
+++ b/src/goal_base.h
@@ -0,0 +1,44 @@
+/* $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 goal_base.h Goal base class. */
+
+#ifndef GOAL_BASE_H
+#define GOAL_BASE_H
+
+#include "cargo_type.h"
+#include "company_type.h"
+#include "goal_type.h"
+#include "core/pool_type.hpp"
+
+typedef Pool<Goal, GoalID, 1, MAX_COMPANIES> GoalPool;
+extern GoalPool _goal_pool;
+
+/** Struct about subsidies, offered and awarded */
+struct Goal : GoalPool::PoolItem<&_goal_pool> {
+ CompanyByte company; ///< Goal is for a specific company; INVALID_COMPANY if it is global
+ GoalTypeByte type; ///< Type of the goal
+ GoalTypeID dst; ///< Index of type
+ char *text; ///< Text of the goal.
+
+ /**
+ * We need an (empty) constructor so struct isn't zeroed (as C++ standard states)
+ */
+ FORCEINLINE Goal() { }
+
+ /**
+ * (Empty) destructor has to be defined else operator delete might be called with NULL parameter
+ */
+ FORCEINLINE ~Goal() { free(this->text); }
+};
+
+#define FOR_ALL_GOALS_FROM(var, start) FOR_ALL_ITEMS_FROM(Goal, goal_index, var, start)
+#define FOR_ALL_GOALS(var) FOR_ALL_GOALS_FROM(var, 0)
+
+#endif /* GOAL_BASE_H */
diff --git a/src/goal_gui.cpp b/src/goal_gui.cpp
new file mode 100644
index 000000000..aeba8e576
--- /dev/null
+++ b/src/goal_gui.cpp
@@ -0,0 +1,253 @@
+/* $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 goal_gui.cpp GUI for goals. */
+
+#include "stdafx.h"
+#include "industry.h"
+#include "town.h"
+#include "window_gui.h"
+#include "strings_func.h"
+#include "date_func.h"
+#include "viewport_func.h"
+#include "gfx_func.h"
+#include "gui.h"
+#include "goal_base.h"
+#include "core/geometry_func.hpp"
+
+#include "widgets/goal_widget.h"
+
+#include "table/strings.h"
+
+struct GoalListWindow : Window {
+ Scrollbar *vscroll;
+
+ GoalListWindow(const WindowDesc *desc, WindowNumber window_number) : Window()
+ {
+ this->CreateNestedTree(desc);
+ this->vscroll = this->GetScrollbar(WID_GL_SCROLLBAR);
+ this->FinishInitNested(desc, window_number);
+ this->OnInvalidateData(0);
+ }
+
+ virtual void OnClick(Point pt, int widget, int click_count)
+ {
+ if (widget != WID_GL_PANEL) return;
+
+ int y = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_GL_PANEL, WD_FRAMERECT_TOP);
+ int num = 0;
+ const Goal *s;
+ FOR_ALL_GOALS(s) {
+ if (s->company == INVALID_COMPANY) {
+ y--;
+ if (y == 0) {
+ this->HandleClick(s);
+ return;
+ }
+ num++;
+ }
+ }
+
+ if (num == 0) {
+ y--; // "None"
+ if (y < 0) return;
+ }
+
+ y -= 2; // "Company specific goals:"
+ if (y < 0) return;
+
+ FOR_ALL_GOALS(s) {
+ if (s->company != INVALID_COMPANY) {
+ y--;
+ if (y == 0) {
+ this->HandleClick(s);
+ return;
+ }
+ }
+ }
+ }
+
+ void HandleClick(const Goal *s)
+ {
+ /* determine dst coordinate for goal and try to scroll to it */
+ TileIndex xy;
+ switch (s->type) {
+ case GT_NONE: return;
+ case GT_COMPANY: return;
+
+ case GT_TILE:
+ if (!IsValidTile(s->dst)) return;
+ xy = s->dst;
+ break;
+
+ case GT_INDUSTRY:
+ if (!Industry::IsValidID(s->dst)) return;
+ xy = Industry::Get(s->dst)->location.tile;
+ break;
+
+ case GT_TOWN:
+ if (!Town::IsValidID(s->dst)) return;
+ xy = Town::Get(s->dst)->xy;
+ break;
+
+ default: NOT_REACHED();
+ }
+
+ if (_ctrl_pressed) {
+ ShowExtraViewPortWindow(xy);
+ } else {
+ ScrollMainWindowToTile(xy);
+ }
+ }
+
+ /**
+ * Count the number of lines in this window.
+ * @return the number of lines
+ */
+ uint CountLines()
+ {
+ /* Count number of (non) awarded goals */
+ uint num_global = 0;
+ uint num_company = 0;
+ const Goal *s;
+ FOR_ALL_GOALS(s) {
+ if (s->company == INVALID_COMPANY) {
+ num_global++;
+ } else {
+ num_company++;
+ }
+ }
+
+ /* Count the 'none' lines */
+ if (num_global == 0) num_global = 1;
+ if (num_company == 0) num_company = 1;
+
+ /* Global, company and an empty line before the accepted ones. */
+ return 3 + num_global + num_company;
+ }
+
+ virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
+ {
+ if (widget != WID_GL_PANEL) return;
+ Dimension d = maxdim(GetStringBoundingBox(STR_GOALS_GLOBAL_TITLE), GetStringBoundingBox(STR_GOALS_COMPANY_TITLE));
+
+ resize->height = d.height;
+
+ d.height *= 5;
+ d.width += padding.width + WD_FRAMERECT_RIGHT + WD_FRAMERECT_LEFT;
+ d.height += padding.height + WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM;
+ *size = maxdim(*size, d);
+ }
+
+ virtual void DrawWidget(const Rect &r, int widget) const
+ {
+ if (widget != WID_GL_PANEL) return;
+
+ YearMonthDay ymd;
+ ConvertDateToYMD(_date, &ymd);
+
+ int right = r.right - WD_FRAMERECT_RIGHT;
+ int y = r.top + WD_FRAMERECT_TOP;
+ int x = r.left + WD_FRAMERECT_LEFT;
+
+ int pos = -this->vscroll->GetPosition();
+ const int cap = this->vscroll->GetCapacity();
+
+ /* Section for drawing the global goals */
+ if (IsInsideMM(pos, 0, cap)) DrawString(x, right, y + pos * FONT_HEIGHT_NORMAL, STR_GOALS_GLOBAL_TITLE);
+ pos++;
+
+ uint num = 0;
+ const Goal *s;
+ FOR_ALL_GOALS(s) {
+ if (s->company == INVALID_COMPANY) {
+ if (IsInsideMM(pos, 0, cap)) {
+ /* Display the goal */
+ SetDParamStr(0, s->text);
+ DrawString(x, right, y + pos * FONT_HEIGHT_NORMAL, STR_GOALS_TEXT);
+ }
+ pos++;
+ num++;
+ }
+ }
+
+ if (num == 0) {
+ if (IsInsideMM(pos, 0, cap)) DrawString(x, right, y + pos * FONT_HEIGHT_NORMAL, STR_GOALS_NONE);
+ pos++;
+ }
+
+ /* Section for drawing the company goals */
+ pos++;
+ if (IsInsideMM(pos, 0, cap)) DrawString(x, right, y + pos * FONT_HEIGHT_NORMAL, STR_GOALS_COMPANY_TITLE);
+ pos++;
+ num = 0;
+
+ FOR_ALL_GOALS(s) {
+ if (s->company != INVALID_COMPANY) {
+ if (IsInsideMM(pos, 0, cap)) {
+ /* Display the goal */
+ SetDParamStr(0, s->text);
+ DrawString(x, right, y + pos * FONT_HEIGHT_NORMAL, STR_GOALS_TEXT);
+ }
+ pos++;
+ num++;
+ }
+ }
+
+ if (num == 0) {
+ if (IsInsideMM(pos, 0, cap)) DrawString(x, right, y + pos * FONT_HEIGHT_NORMAL, STR_GOALS_NONE);
+ pos++;
+ }
+ }
+
+ virtual void OnResize()
+ {
+ this->vscroll->SetCapacityFromWidget(this, WID_GL_PANEL);
+ }
+
+ /**
+ * Some data on this window has become invalid.
+ * @param data Information about the changed data.
+ * @param gui_scope Whether the call is done from GUI scope. You may not do everything when not in GUI scope. See #InvalidateWindowData() for details.
+ */
+ virtual void OnInvalidateData(int data = 0, bool gui_scope = true)
+ {
+ if (!gui_scope) return;
+ this->vscroll->SetCount(this->CountLines());
+ }
+};
+
+static const NWidgetPart _nested_goals_list_widgets[] = {
+ NWidget(NWID_HORIZONTAL),
+ NWidget(WWT_CLOSEBOX, COLOUR_BROWN),
+ NWidget(WWT_CAPTION, COLOUR_BROWN), SetDataTip(STR_GOALS_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
+ NWidget(WWT_SHADEBOX, COLOUR_BROWN),
+ NWidget(WWT_STICKYBOX, COLOUR_BROWN),
+ EndContainer(),
+ NWidget(NWID_HORIZONTAL),
+ NWidget(WWT_PANEL, COLOUR_BROWN, WID_GL_PANEL), SetDataTip(0x0, STR_GOALS_TOOLTIP_CLICK_ON_SERVICE_TO_CENTER), SetResize(1, 1), SetScrollbar(WID_GL_SCROLLBAR), EndContainer(),
+ NWidget(NWID_VERTICAL),
+ NWidget(NWID_VSCROLLBAR, COLOUR_BROWN, WID_GL_SCROLLBAR),
+ NWidget(WWT_RESIZEBOX, COLOUR_BROWN),
+ EndContainer(),
+ EndContainer(),
+};
+
+static const WindowDesc _goals_list_desc(
+ WDP_AUTO, 500, 127,
+ WC_GOALS_LIST, WC_NONE,
+ 0,
+ _nested_goals_list_widgets, lengthof(_nested_goals_list_widgets)
+);
+
+
+void ShowGoalsList()
+{
+ AllocateWindowDescFront<GoalListWindow>(&_goals_list_desc, 0);
+}
diff --git a/src/goal_type.h b/src/goal_type.h
new file mode 100644
index 000000000..5014b1b21
--- /dev/null
+++ b/src/goal_type.h
@@ -0,0 +1,33 @@
+/* $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 goal_type.h basic types related to goals */
+
+#ifndef GOAL_TYPE_H
+#define GOAL_TYPE_H
+
+/** Types of goal destinations */
+enum GoalType {
+ GT_NONE, ///< Destination is not linked
+ GT_TILE, ///< Destination is a tile
+ GT_INDUSTRY, ///< Destination is an industry
+ GT_TOWN, ///< Destination is a town
+ GT_COMPANY, ///< Destination is a company
+};
+typedef SimpleTinyEnumT<GoalType, byte> GoalTypeByte; ///< The GoalType packed into a byte for savegame purposes.
+
+typedef uint32 GoalTypeID; ///< Contains either tile, industry ID, town ID or company ID (or INVALID_GOALTYPE)
+static const GoalTypeID INVALID_GOALTYPE = 0xFFFFFFFF; ///< Invalid/unknown index of GoalType
+
+typedef uint16 GoalID; ///< ID of a goal
+struct Goal;
+
+extern GoalID _new_goal_id;
+
+#endif /* GOAL_TYPE_H */
diff --git a/src/gui.h b/src/gui.h
index 4859fe79e..a83dd8fc7 100644
--- a/src/gui.h
+++ b/src/gui.h
@@ -52,6 +52,7 @@ void ShowBuildTreesToolbar();
void ShowTownDirectory();
void ShowIndustryDirectory();
void ShowSubsidiesList();
+void ShowGoalsList();
void ShowEstimatedCostOrIncome(Money cost, int x, int y);
diff --git a/src/lang/english.txt b/src/lang/english.txt
index aa6c9b63a..e73a8f879 100644
--- a/src/lang/english.txt
+++ b/src/lang/english.txt
@@ -382,6 +382,7 @@ STR_TOWN_MENU_FOUND_TOWN :Found town
############ range for subsidies menu starts
STR_SUBSIDIES_MENU_SUBSIDIES :Subsidies
+STR_SUBSIDIES_MENU_GOAL :Current goals
############ range ends here
############ range for graph menu starts
@@ -2657,6 +2658,14 @@ STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_NEW_BUILDINGS :{YELLOW}Fund th
STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_EXCLUSIVE_TRANSPORT :{YELLOW}Buy 1 year's exclusive transport rights in town. Town authority will only allow passengers and cargo to use your company's stations.{}Cost: {CURRENCY_LONG}
STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_BRIBE :{YELLOW}Bribe the local authority to increase your rating, at the risk of a severe penalty if caught.{}Cost: {CURRENCY_LONG}
+# Goal window
+STR_GOALS_CAPTION :{WHITE}Goals
+STR_GOALS_GLOBAL_TITLE :{BLACK}Global goals:
+STR_GOALS_TEXT :{ORANGE}{RAW_STRING}
+STR_GOALS_NONE :{ORANGE}- None -
+STR_GOALS_COMPANY_TITLE :{BLACK}Company goals:
+STR_GOALS_TOOLTIP_CLICK_ON_SERVICE_TO_CENTER :{BLACK}Click on goal to centre main view on industry/town/tile. Ctrl+Click opens a new viewport on industry/town/tile location
+
# Subsidies window
STR_SUBSIDIES_CAPTION :{WHITE}Subsidies
STR_SUBSIDIES_OFFERED_TITLE :{BLACK}Subsidies on offer for services taking:
diff --git a/src/saveload/goal_sl.cpp b/src/saveload/goal_sl.cpp
new file mode 100644
index 000000000..721909a77
--- /dev/null
+++ b/src/saveload/goal_sl.cpp
@@ -0,0 +1,45 @@
+/* $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 goal_sl.cpp Code handling saving and loading of goals */
+
+#include "../stdafx.h"
+#include "../goal_base.h"
+
+#include "saveload.h"
+
+static const SaveLoad _goals_desc[] = {
+ SLE_VAR(Goal, company, SLE_UINT16),
+ SLE_VAR(Goal, type, SLE_UINT16),
+ SLE_VAR(Goal, dst, SLE_UINT32),
+ SLE_STR(Goal, text, SLE_STR, 0),
+ SLE_END()
+};
+
+static void Save_GOAL()
+{
+ Goal *s;
+ FOR_ALL_GOALS(s) {
+ SlSetArrayIndex(s->index);
+ SlObject(s, _goals_desc);
+ }
+}
+
+static void Load_GOAL()
+{
+ int index;
+ while ((index = SlIterateArray()) != -1) {
+ Goal *s = new (index) Goal();
+ SlObject(s, _goals_desc);
+ }
+}
+
+extern const ChunkHandler _goal_chunk_handlers[] = {
+ { 'GOAL', Save_GOAL, Load_GOAL, NULL, NULL, CH_ARRAY | CH_LAST},
+};
diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp
index fe4053741..b45d105cf 100644
--- a/src/saveload/saveload.cpp
+++ b/src/saveload/saveload.cpp
@@ -402,6 +402,7 @@ extern const ChunkHandler _station_chunk_handlers[];
extern const ChunkHandler _industry_chunk_handlers[];
extern const ChunkHandler _economy_chunk_handlers[];
extern const ChunkHandler _subsidy_chunk_handlers[];
+extern const ChunkHandler _goal_chunk_handlers[];
extern const ChunkHandler _ai_chunk_handlers[];
extern const ChunkHandler _game_chunk_handlers[];
extern const ChunkHandler _animated_tile_chunk_handlers[];
@@ -429,6 +430,7 @@ static const ChunkHandler * const _chunk_handlers[] = {
_industry_chunk_handlers,
_economy_chunk_handlers,
_subsidy_chunk_handlers,
+ _goal_chunk_handlers,
_engine_chunk_handlers,
_town_chunk_handlers,
_sign_chunk_handlers,
diff --git a/src/script/api/game/game_goal.hpp.sq b/src/script/api/game/game_goal.hpp.sq
new file mode 100644
index 000000000..54b1c6aeb
--- /dev/null
+++ b/src/script/api/game/game_goal.hpp.sq
@@ -0,0 +1,36 @@
+/* $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_goal.hpp"
+#include "../template/template_goal.hpp.sq"
+
+
+template <> const char *GetClassName<ScriptGoal, ST_GS>() { return "GSGoal"; }
+
+void SQGSGoal_Register(Squirrel *engine)
+{
+ DefSQClass<ScriptGoal, ST_GS> SQGSGoal("GSGoal");
+ SQGSGoal.PreRegister(engine);
+ SQGSGoal.AddConstructor<void (ScriptGoal::*)(), 1>(engine, "x");
+
+ SQGSGoal.DefSQConst(engine, ScriptGoal::GOAL_INVALID, "GOAL_INVALID");
+ SQGSGoal.DefSQConst(engine, ScriptGoal::GT_NONE, "GT_NONE");
+ SQGSGoal.DefSQConst(engine, ScriptGoal::GT_TILE, "GT_TILE");
+ SQGSGoal.DefSQConst(engine, ScriptGoal::GT_INDUSTRY, "GT_INDUSTRY");
+ SQGSGoal.DefSQConst(engine, ScriptGoal::GT_TOWN, "GT_TOWN");
+ SQGSGoal.DefSQConst(engine, ScriptGoal::GT_COMPANY, "GT_COMPANY");
+
+ SQGSGoal.DefSQStaticMethod(engine, &ScriptGoal::IsValidGoal, "IsValidGoal", 2, ".i");
+ SQGSGoal.DefSQStaticMethod(engine, &ScriptGoal::New, "New", 5, ".i.ii");
+ SQGSGoal.DefSQStaticMethod(engine, &ScriptGoal::Remove, "Remove", 2, ".i");
+
+ SQGSGoal.PostRegister(engine);
+}
diff --git a/src/script/api/script_goal.cpp b/src/script/api/script_goal.cpp
new file mode 100644
index 000000000..85aaeedb6
--- /dev/null
+++ b/src/script/api/script_goal.cpp
@@ -0,0 +1,51 @@
+/* $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_goal.cpp Implementation of ScriptGoal. */
+
+#include "../../stdafx.h"
+#include "script_goal.hpp"
+#include "script_error.hpp"
+#include "script_industry.hpp"
+#include "script_map.hpp"
+#include "script_town.hpp"
+#include "../script_instance.hpp"
+#include "../../command_type.h"
+#include "../../settings_type.h"
+#include "../../openttd.h"
+#include "../../network/network.h"
+#include "../../goal_base.h"
+#include "../../string_func.h"
+
+/* static */ bool ScriptGoal::IsValidGoal(GoalID goal_id)
+{
+ return ::Goal::IsValidID(goal_id);
+}
+
+/* static */ ScriptGoal::GoalID ScriptGoal::New(ScriptCompany::CompanyID company, const char *goal, GoalType type, uint32 destination)
+{
+ EnforcePrecondition(GOAL_INVALID, !StrEmpty(goal));
+ EnforcePrecondition(GOAL_INVALID, company == ScriptCompany::COMPANY_INVALID || ScriptCompany::ResolveCompanyID(company) != ScriptCompany::COMPANY_INVALID);
+ EnforcePrecondition(GOAL_INVALID, (type == GT_NONE && destination == 0) || (type == GT_TILE && ScriptMap::IsValidTile(destination)) || (type == GT_INDUSTRY && ScriptIndustry::IsValidIndustry(destination)) || (type == GT_TOWN && ScriptTown::IsValidTown(destination)) || (type == GT_COMPANY && ScriptCompany::ResolveCompanyID((ScriptCompany::CompanyID)destination) != ScriptCompany::COMPANY_INVALID));
+
+ uint8 c = company;
+ if (company == ScriptCompany::COMPANY_INVALID) c = INVALID_COMPANY;
+
+ if (!ScriptObject::DoCommand(0, type | (c << 8), destination, CMD_CREATE_GOAL, goal, &ScriptInstance::DoCommandReturnGoalID)) return GOAL_INVALID;
+
+ /* In case of test-mode, we return GoalID 0 */
+ return (ScriptGoal::GoalID)0;
+}
+
+/* static */ bool ScriptGoal::Remove(GoalID goal_id)
+{
+ EnforcePrecondition(false, IsValidGoal(goal_id));
+
+ return ScriptObject::DoCommand(0, goal_id, 0, CMD_REMOVE_GOAL);
+}
diff --git a/src/script/api/script_goal.hpp b/src/script/api/script_goal.hpp
new file mode 100644
index 000000000..ac7d8f449
--- /dev/null
+++ b/src/script/api/script_goal.hpp
@@ -0,0 +1,73 @@
+/* $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_goal.hpp Everything to manipulate the current running goal. */
+
+#ifndef SCRIPT_GOAL_HPP
+#define SCRIPT_GOAL_HPP
+
+#include "script_object.hpp"
+#include "script_company.hpp"
+#include "../../goal_type.h"
+
+/**
+ * Class that handles some goal related functions.
+ * @api game
+ */
+class ScriptGoal : public ScriptObject {
+public:
+ /**
+ * The goal IDs.
+ */
+ enum GoalID {
+ /* Note: these values represent part of the in-game GoalID enum */
+ GOAL_INVALID = ::INVALID_GOALTYPE, ///< An invalid goal id.
+ };
+
+ /**
+ * Goal types that can be given to a goal.
+ */
+ enum GoalType {
+ /* Note: these values represent part of the in-game GoalType enum */
+ GT_NONE = ::GT_NONE, ///< Destination is not linked.
+ GT_TILE = ::GT_TILE, ///< Destination is a tile.
+ GT_INDUSTRY = ::GT_INDUSTRY, ///< Destination is an industry.
+ GT_TOWN = ::GT_TOWN, ///< Destination is a town.
+ GT_COMPANY = ::GT_COMPANY, ///< Destination is a company.
+ };
+
+ /**
+ * Check whether this is a valid goalID.
+ * @param goal_id The GoalID to check.
+ * @return True if and only if this goal is valid.
+ */
+ static bool IsValidGoal(GoalID goal_id);
+
+ /**
+ * Create a new goal.
+ * @param company The company to create the goal for, or ScriptCompany::COMPANY_INVALID for all.
+ * @param goal The goal to add to the GUI.
+ * @param type The type of the goal.
+ * @param destination The destination of the #type type.
+ * @return The new GoalID, or GOAL_INVALID if it failed.
+ * @pre goal != NULL.
+ * @pre company == COMPANY_INVALID || ResolveCompanyID(company) != COMPANY_INVALID.
+ */
+ static GoalID New(ScriptCompany::CompanyID company, const char *goal, GoalType type, uint32 destination);
+
+ /**
+ * Remove a goal from the list.
+ * @param goal_id The goal to remove.
+ * @return True if the action succeeded.
+ * @pre IsValidGoal(goal_id).
+ */
+ static bool Remove(GoalID goal_id);
+};
+
+#endif /* SCRIPT_GOAL_HPP */
diff --git a/src/script/api/script_object.cpp b/src/script/api/script_object.cpp
index d9a432b44..72185c786 100644
--- a/src/script/api/script_object.cpp
+++ b/src/script/api/script_object.cpp
@@ -16,6 +16,7 @@
#include "../../network/network.h"
#include "../../tunnelbridge.h"
#include "../../genworld.h"
+#include "../../goal_type.h"
#include "../script_storage.hpp"
#include "../script_instance.hpp"
@@ -142,6 +143,7 @@ ScriptObject::ActiveInstance::~ActiveInstance()
SetNewVehicleID(_new_vehicle_id);
SetNewSignID(_new_sign_id);
SetNewGroupID(_new_group_id);
+ SetNewGoalID(_new_goal_id);
}
/* static */ bool ScriptObject::GetLastCommandRes()
@@ -179,6 +181,16 @@ ScriptObject::ActiveInstance::~ActiveInstance()
return GetStorage()->new_group_id;
}
+/* static */ void ScriptObject::SetNewGoalID(GoalID goal_id)
+{
+ GetStorage()->new_goal_id = goal_id;
+}
+
+/* static */ GroupID ScriptObject::GetNewGoalID()
+{
+ return GetStorage()->new_goal_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 d12f006ee..86bdbf8df 100644
--- a/src/script/api/script_object.hpp
+++ b/src/script/api/script_object.hpp
@@ -161,6 +161,11 @@ protected:
static GroupID GetNewGroupID();
/**
+ * Get the latest stored new_goal_id.
+ */
+ static GoalID GetNewGoalID();
+
+ /**
* Store a allow_do_command per company.
* @param allow The new allow.
*/
@@ -228,6 +233,12 @@ private:
* @param group_id The new GroupID.
*/
static void SetNewGroupID(GroupID group_id);
+
+ /**
+ * Store a new_goal_id per company.
+ * @param goal_id The new GoalID.
+ */
+ static void SetNewGoalID(GoalID goal_id);
};
#endif /* SCRIPT_OBJECT_HPP */
diff --git a/src/script/api/script_types.hpp b/src/script/api/script_types.hpp
index 1cce06571..2b763f4f5 100644
--- a/src/script/api/script_types.hpp
+++ b/src/script/api/script_types.hpp
@@ -32,6 +32,10 @@
* <td> introduction, preview \ref dynamic_engines "(2)" </td>
* <td> engines retires \ref dynamic_engines "(2)" </td>
* <td> no \ref dynamic_engines "(2)" </td></tr>
+ * <tr><td>#GoalID </td><td> goal </td>
+ * <td> creation </td>
+ * <td> deletion </td>
+ * <td> yes </td></tr>
* <tr><td>#GroupID </td><td> vehicle group </td>
* <td> creation </td>
* <td> deletion </td>
@@ -87,6 +91,7 @@ typedef uint BridgeType; ///< Internal name, not of any use for you.
typedef byte CargoID; ///< The ID of a cargo.
class CommandCost; ///< The cost of a command.
typedef uint16 EngineID; ///< The ID of an engine.
+typedef uint16 GoalID; ///< The ID of a goal.
typedef uint16 GroupID; ///< The ID of a group.
typedef uint16 IndustryID; ///< The ID of an industry.
typedef uint8 IndustryType; ///< The ID of an industry-type.
diff --git a/src/script/api/template/template_goal.hpp.sq b/src/script/api/template/template_goal.hpp.sq
new file mode 100644
index 000000000..012864324
--- /dev/null
+++ b/src/script/api/template/template_goal.hpp.sq
@@ -0,0 +1,27 @@
+/* $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_goal.hpp"
+
+namespace SQConvert {
+ /* Allow enums to be used as Squirrel parameters */
+ template <> inline ScriptGoal::GoalID GetParam(ForceType<ScriptGoal::GoalID>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptGoal::GoalID)tmp; }
+ template <> inline int Return<ScriptGoal::GoalID>(HSQUIRRELVM vm, ScriptGoal::GoalID res) { sq_pushinteger(vm, (int32)res); return 1; }
+ template <> inline ScriptGoal::GoalType GetParam(ForceType<ScriptGoal::GoalType>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (ScriptGoal::GoalType)tmp; }
+ template <> inline int Return<ScriptGoal::GoalType>(HSQUIRRELVM vm, ScriptGoal::GoalType res) { sq_pushinteger(vm, (int32)res); return 1; }
+
+ /* Allow ScriptGoal to be used as Squirrel parameter */
+ template <> inline ScriptGoal *GetParam(ForceType<ScriptGoal *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (ScriptGoal *)instance; }
+ template <> inline ScriptGoal &GetParam(ForceType<ScriptGoal &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(ScriptGoal *)instance; }
+ template <> inline const ScriptGoal *GetParam(ForceType<const ScriptGoal *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (ScriptGoal *)instance; }
+ template <> inline const ScriptGoal &GetParam(ForceType<const ScriptGoal &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(ScriptGoal *)instance; }
+ template <> inline int Return<ScriptGoal *>(HSQUIRRELVM vm, ScriptGoal *res) { if (res == NULL) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, "Goal", res, NULL, DefSQDestructorCallback<ScriptGoal>, true); return 1; }
+} // namespace SQConvert
diff --git a/src/script/script_instance.cpp b/src/script/script_instance.cpp
index 7a6b4fe70..641d939d3 100644
--- a/src/script/script_instance.cpp
+++ b/src/script/script_instance.cpp
@@ -245,6 +245,11 @@ void ScriptInstance::CollectGarbage() const
instance->engine->InsertResult(ScriptObject::GetNewGroupID());
}
+/* static */ void ScriptInstance::DoCommandReturnGoalID(ScriptInstance *instance)
+{
+ instance->engine->InsertResult(ScriptObject::GetNewGoalID());
+}
+
ScriptStorage *ScriptInstance::GetStorage()
{
return this->storage;
diff --git a/src/script/script_instance.hpp b/src/script/script_instance.hpp
index d24a40827..7617e370f 100644
--- a/src/script/script_instance.hpp
+++ b/src/script/script_instance.hpp
@@ -100,6 +100,11 @@ public:
static void DoCommandReturnGroupID(ScriptInstance *instance);
/**
+ * Return a GoalID reply for a DoCommand.
+ */
+ static void DoCommandReturnGoalID(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 57cdc60ad..0af56b2b4 100644
--- a/src/script/script_storage.hpp
+++ b/src/script/script_storage.hpp
@@ -16,6 +16,7 @@
#include "../vehicle_func.h"
#include "../road_type.h"
#include "../group.h"
+#include "../goal_type.h"
#include "table/strings.h"
#include <vector>
@@ -45,6 +46,7 @@ private:
VehicleID new_vehicle_id; ///< The ID of the new Vehicle.
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.
std::vector<int> callback_value; ///< The values which need to survive a callback.
diff --git a/src/toolbar_gui.cpp b/src/toolbar_gui.cpp
index 84de5876b..de1fb73bf 100644
--- a/src/toolbar_gui.cpp
+++ b/src/toolbar_gui.cpp
@@ -475,7 +475,7 @@ static CallBackFunction MenuClickTown(int index)
static CallBackFunction ToolbarSubsidiesClick(Window *w)
{
- PopupMainToolbMenu(w, WID_TN_SUBSIDIES, STR_SUBSIDIES_MENU_SUBSIDIES, 1);
+ PopupMainToolbMenu(w, WID_TN_SUBSIDIES, STR_SUBSIDIES_MENU_SUBSIDIES, 2);
return CBF_NONE;
}
@@ -487,7 +487,10 @@ static CallBackFunction ToolbarSubsidiesClick(Window *w)
*/
static CallBackFunction MenuClickSubsidies(int index)
{
- ShowSubsidiesList();
+ switch (index) {
+ case 0: ShowSubsidiesList(); break;
+ case 1: ShowGoalsList(); break;
+ }
return CBF_NONE;
}
diff --git a/src/widgets/goal_widget.h b/src/widgets/goal_widget.h
new file mode 100644
index 000000000..aaa91acc3
--- /dev/null
+++ b/src/widgets/goal_widget.h
@@ -0,0 +1,22 @@
+
+/* $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 goal_widget.h Types related to the goal widgets. */
+
+#ifndef WIDGETS_GOAL_WIDGET_H
+#define WIDGETS_GOAL_WIDGET_H
+
+/** Widgets of the #GoalListWindow class. */
+enum GoalListWidgets {
+ WID_GL_PANEL, ///< Panel of the window.
+ WID_GL_SCROLLBAR, ///< Scrollbar of the panel.
+};
+
+#endif /* WIDGETS_GOAL_WIDGET_H */
diff --git a/src/window_type.h b/src/window_type.h
index 975103667..921e71dbc 100644
--- a/src/window_type.h
+++ b/src/window_type.h
@@ -277,6 +277,12 @@ enum WindowClass {
*/
WC_AI_LIST,
+ /**
+ * Goals list; Window numbers:
+ * - 0 ; #GoalListWidgets
+ */
+ WC_GOALS_LIST,
+
/**
* Station list; Window numbers: