Make it possible to stop road vehicles from slowing down in curves so "diagonal"...
[openttd-joker.git] / src / plans_base.h
blob6a88683aec4d0723d280e03f3047fa58ec4c2a05
1 /* $Id$ */
3 /*
4 * This file is part of OpenTTD.
5 * 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.
6 * 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.
7 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
8 */
10 /** @file plans_base.h Base class for plans. */
12 #ifndef PLANS_BASE_H
13 #define PLANS_BASE_H
15 #include "plans_func.h"
16 #include "core/pool_type.hpp"
17 #include "company_type.h"
18 #include "company_func.h"
19 #include "command_func.h"
20 #include "map_func.h"
21 #include "date_func.h"
22 #include "viewport_func.h"
23 #include "core/endian_func.hpp"
24 #include <string>
25 #include <vector>
27 typedef Pool<Plan, PlanID, 16, 64000> PlanPool;
28 typedef std::vector<TileIndex> TileVector;
29 typedef std::vector<PlanLine*> PlanLineVector;
30 extern PlanPool _plan_pool;
32 struct PlanLine {
33 bool visible;
34 bool focused;
35 TileVector tiles;
37 PlanLine()
39 this->visible = true;
40 this->focused = false;
43 ~PlanLine()
45 this->Clear();
48 void Clear()
50 this->tiles.clear();
53 bool AppendTile(TileIndex tile)
55 const uint cnt = (uint) this->tiles.size();
57 if (cnt > 0) {
58 const TileIndex last_tile = this->tiles[cnt - 1];
59 if (last_tile == tile) return false;
60 MarkTileLineDirty(last_tile, tile);
62 if (cnt > 1) {
63 const TileIndex t0 = this->tiles[cnt - 2];
64 const int x0 = (int)TileX(t0);
65 const int y0 = (int)TileY(t0);
66 const TileIndex t1 = this->tiles[cnt - 1];
67 const int x1 = (int)TileX(t1);
68 const int y1 = (int)TileY(t1);
69 const int x2 = (int)TileX(tile);
70 const int y2 = (int)TileY(tile);
72 if ((y1 - y0) * (x2 - x1) == (y2 - y1) * (x1 - x0)) { // Same direction.
73 if (abs(x2 - x1) <= abs(x2 - x0) && abs(y2 - y1) <= abs(y2 - y0)) { // Tile i+1 is between i and i+2.
74 /* The new tile is in the continuity, just update the last tile. */
75 this->tiles[cnt - 1] = tile;
76 MarkTileLineDirty(t1, tile);
77 return true;
83 if (this->tiles.size() * sizeof(TileIndex) >= MAX_CMD_TEXT_LENGTH) return false;
85 this->tiles.push_back(tile);
86 return true;
89 void SetFocus(bool focused)
91 if (this->focused != focused) this->MarkDirty();
92 this->focused = focused;
95 bool ToggleVisibility()
97 this->SetVisibility(!this->visible);
98 return this->visible;
101 void SetVisibility(bool visible)
103 if (this->visible != visible) this->MarkDirty();
104 this->visible = visible;
107 void MarkDirty()
109 const uint sz = (uint) this->tiles.size();
110 for (uint i = 1; i < sz; i++) {
111 MarkTileLineDirty(this->tiles[i - 1], this->tiles[i]);
115 TileIndex *Export(uint *buffer_length)
117 const uint cnt = (uint) this->tiles.size();
118 const uint datalen = sizeof(TileIndex) * cnt;
119 TileIndex *buffer = (TileIndex *)malloc(datalen);
120 if (buffer) {
121 for (uint i = 0; i < cnt; i++) {
122 buffer[i] = TO_LE32(this->tiles[i]);
124 if (buffer_length) *buffer_length = datalen;
126 return buffer;
129 void Import(const TileIndex* data, const uint data_length)
131 for (uint i = data_length; i != 0; i--, data++) {
132 this->tiles.push_back(FROM_LE32(*data));
136 void AddLineToCalculateCentreTile(uint64 &x, uint64 &y, uint32 &count) const
138 for (size_t i = 0; i < this->tiles.size(); i++) {
139 TileIndex t = this->tiles[i];
140 x += TileX(t);
141 y += TileY(t);
142 count++;
146 TileIndex CalculateCentreTile() const
148 uint64 x = 0;
149 uint64 y = 0;
150 uint32 count = 0;
151 this->AddLineToCalculateCentreTile(x, y, count);
152 if (count == 0) return INVALID_TILE;
153 return TileXY(x / count, y / count);
157 struct Plan : PlanPool::PoolItem<&_plan_pool> {
158 OwnerByte owner;
159 PlanLineVector lines;
160 PlanLine *temp_line;
161 bool visible;
162 bool visible_by_all;
163 bool show_lines;
164 Date creation_date;
165 std::string name;
167 Plan(Owner owner = INVALID_OWNER)
169 this->owner = owner;
170 this->creation_date = _date;
171 this->visible = false;
172 this->visible_by_all = false;
173 this->show_lines = false;
174 this->temp_line = new PlanLine();
175 this->name = "";
178 ~Plan()
180 for (PlanLineVector::iterator it = lines.begin(); it != lines.end(); it++) {
181 delete (*it);
183 this->lines.clear();
184 delete temp_line;
187 void SetFocus(bool focused)
189 for (PlanLineVector::iterator it = lines.begin(); it != lines.end(); it++) {
190 (*it)->SetFocus(focused);
194 void SetVisibility(bool visible, bool do_lines = true)
196 this->visible = visible;
198 if (!do_lines) return;
199 for (PlanLineVector::iterator it = lines.begin(); it != lines.end(); it++) {
200 (*it)->SetVisibility(visible);
204 bool ToggleVisibility()
206 this->SetVisibility(!this->visible);
207 return this->visible;
210 PlanLine *NewLine()
212 PlanLine *pl = new PlanLine();
213 if (pl) this->lines.push_back(pl);
214 return pl;
217 bool StoreTempTile(TileIndex tile)
219 return this->temp_line->AppendTile(tile);
222 bool ValidateNewLine()
224 bool ret = false;
225 if (this->temp_line->tiles.size() > 1) {
226 uint buffer_length = 0;
227 const TileIndex *buffer = this->temp_line->Export(&buffer_length);
228 if (buffer) {
229 _current_plan->SetVisibility(true, false);
230 ret = DoCommandP(0, _current_plan->index, (uint32) this->temp_line->tiles.size(), CMD_ADD_PLAN_LINE, nullptr, (const char *)buffer, true, buffer_length);
231 free(buffer);
233 _current_plan->temp_line->MarkDirty();
234 this->temp_line->Clear();
236 return ret;
239 bool IsListable()
241 return (this->owner == _local_company || this->visible_by_all);
244 bool IsVisible()
246 if (!this->IsListable()) return false;
247 return this->visible;
250 bool HasName() const
252 return !this->name.empty();
255 bool ToggleVisibilityByAll()
257 if (_current_plan->owner == _local_company) DoCommandP(0, _current_plan->index, !this->visible_by_all, CMD_CHANGE_PLAN_VISIBILITY);
258 return this->visible_by_all;
261 const char* GetNameCStr() const
263 return name.c_str();
266 TileIndex CalculateCentreTile() const
268 uint64 x = 0;
269 uint64 y = 0;
270 uint32 count = 0;
271 for (PlanLineVector::const_iterator it = lines.begin(); it != lines.end(); it++) {
272 (*it)->AddLineToCalculateCentreTile(x, y, count);
274 if (count == 0) return INVALID_TILE;
275 return TileXY(x / count, y / count);
279 #define FOR_ALL_PLANS_FROM(var, start) FOR_ALL_ITEMS_FROM(Plan, plan_index, var, start)
280 #define FOR_ALL_PLANS(var) FOR_ALL_PLANS_FROM(var, 0)
282 #endif /* PLANS_BASE_H */