24 #include "yapf/yapf.h" |
24 #include "yapf/yapf.h" |
25 #include "date.h" |
25 #include "date.h" |
26 #include "newgrf.h" |
26 #include "newgrf.h" |
27 #include "string.h" |
27 #include "string.h" |
28 #include "strings.h" |
28 #include "strings.h" |
|
29 #include "misc/autoptr.hpp" |
29 |
30 |
30 enum { |
31 enum { |
31 MAX_WAYPOINTS_PER_TOWN = 64, |
32 MAX_WAYPOINTS_PER_TOWN = 64, |
32 }; |
33 }; |
33 |
34 |
34 /** |
35 DEFINE_OLD_POOL_GENERIC(Waypoint, Waypoint) |
35 * Called if a new block is added to the waypoint-pool |
36 |
36 */ |
|
37 static void WaypointPoolNewBlock(uint start_item) |
|
38 { |
|
39 Waypoint *wp; |
|
40 |
|
41 /* We don't use FOR_ALL here, because FOR_ALL skips invalid items. |
|
42 * TODO - This is just a temporary stage, this will be removed. */ |
|
43 for (wp = GetWaypoint(start_item); wp != NULL; wp = (wp->index + 1U < GetWaypointPoolSize()) ? GetWaypoint(wp->index + 1U) : NULL) wp->index = start_item++; |
|
44 } |
|
45 |
|
46 DEFINE_OLD_POOL(Waypoint, Waypoint, WaypointPoolNewBlock, NULL) |
|
47 |
|
48 /** |
|
49 * Create a new waypoint |
|
50 * @return a pointer to the newly created Waypoint */ |
|
51 static Waypoint* AllocateWaypoint() |
|
52 { |
|
53 Waypoint *wp; |
|
54 |
|
55 /* We don't use FOR_ALL here, because FOR_ALL skips invalid items. |
|
56 * TODO - This is just a temporary stage, this will be removed. */ |
|
57 for (wp = GetWaypoint(0); wp != NULL; wp = (wp->index + 1U < GetWaypointPoolSize()) ? GetWaypoint(wp->index + 1U) : NULL) { |
|
58 if (!IsValidWaypoint(wp)) { |
|
59 uint index = wp->index; |
|
60 |
|
61 memset(wp, 0, sizeof(*wp)); |
|
62 wp->index = index; |
|
63 |
|
64 return wp; |
|
65 } |
|
66 } |
|
67 |
|
68 /* Check if we can add a block to the pool */ |
|
69 if (AddBlockToPool(&_Waypoint_pool)) return AllocateWaypoint(); |
|
70 |
|
71 return NULL; |
|
72 } |
|
73 |
37 |
74 /** |
38 /** |
75 * Update the sign for the waypoint |
39 * Update the sign for the waypoint |
76 * @param wp Waypoint to update sign */ |
40 * @param wp Waypoint to update sign */ |
77 static void UpdateWaypointSign(Waypoint* wp) |
41 static void UpdateWaypointSign(Waypoint* wp) |
101 Waypoint *wp; |
65 Waypoint *wp; |
102 |
66 |
103 FOR_ALL_WAYPOINTS(wp) { |
67 FOR_ALL_WAYPOINTS(wp) { |
104 UpdateWaypointSign(wp); |
68 UpdateWaypointSign(wp); |
105 } |
69 } |
106 } |
|
107 |
|
108 /** |
|
109 * Internal handler to delete a waypoint |
|
110 * @param wp Waypoint to delete |
|
111 */ |
|
112 void DestroyWaypoint(Waypoint *wp) |
|
113 { |
|
114 RemoveOrderFromAllVehicles(OT_GOTO_WAYPOINT, wp->index); |
|
115 |
|
116 if (wp->string != STR_NULL) DeleteName(wp->string); |
|
117 |
|
118 RedrawWaypointSign(wp); |
|
119 } |
70 } |
120 |
71 |
121 /** |
72 /** |
122 * Set the default name for a waypoint |
73 * Set the default name for a waypoint |
123 * @param wp Waypoint to work on |
74 * @param wp Waypoint to work on |
204 * distingush between "Flat land required" and "land sloped in wrong direction" |
155 * distingush between "Flat land required" and "land sloped in wrong direction" |
205 */ |
156 */ |
206 CommandCost CmdBuildTrainWaypoint(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
157 CommandCost CmdBuildTrainWaypoint(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
207 { |
158 { |
208 Waypoint *wp; |
159 Waypoint *wp; |
|
160 AutoPtrT<Waypoint> wp_auto_delete; |
209 Slope tileh; |
161 Slope tileh; |
210 Axis axis; |
162 Axis axis; |
211 |
163 |
212 SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); |
164 SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); |
213 |
165 |
234 if (MayHaveBridgeAbove(tile) && IsBridgeAbove(tile)) return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST); |
186 if (MayHaveBridgeAbove(tile) && IsBridgeAbove(tile)) return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST); |
235 |
187 |
236 /* Check if there is an already existing, deleted, waypoint close to us that we can reuse. */ |
188 /* Check if there is an already existing, deleted, waypoint close to us that we can reuse. */ |
237 wp = FindDeletedWaypointCloseTo(tile); |
189 wp = FindDeletedWaypointCloseTo(tile); |
238 if (wp == NULL) { |
190 if (wp == NULL) { |
239 wp = AllocateWaypoint(); |
191 wp = new Waypoint(tile); |
240 if (wp == NULL) return CMD_ERROR; |
192 if (wp == NULL) return CMD_ERROR; |
|
193 |
|
194 wp_auto_delete = wp; |
241 |
195 |
242 wp->town_index = 0; |
196 wp->town_index = 0; |
243 wp->string = STR_NULL; |
197 wp->string = STR_NULL; |
244 wp->town_cn = 0; |
198 wp->town_cn = 0; |
245 } |
199 } |
262 wp->grfid = 0; |
216 wp->grfid = 0; |
263 wp->localidx = 0; |
217 wp->localidx = 0; |
264 } |
218 } |
265 |
219 |
266 wp->deleted = 0; |
220 wp->deleted = 0; |
267 wp->xy = tile; |
|
268 wp->build_date = _date; |
221 wp->build_date = _date; |
269 |
222 |
270 if (wp->town_index == 0) MakeDefaultWaypointName(wp); |
223 if (wp->town_index == 0) MakeDefaultWaypointName(wp); |
271 |
224 |
272 UpdateWaypointSign(wp); |
225 UpdateWaypointSign(wp); |
273 RedrawWaypointSign(wp); |
226 RedrawWaypointSign(wp); |
274 YapfNotifyTrackLayoutChange(tile, AxisToTrack(axis)); |
227 YapfNotifyTrackLayoutChange(tile, AxisToTrack(axis)); |
|
228 wp_auto_delete.Detach(); |
275 } |
229 } |
276 |
230 |
277 return CommandCost(_price.build_train_depot); |
231 return CommandCost(_price.build_train_depot); |
278 } |
232 } |
279 |
233 |
441 if (!DrawStationTile(x, y, railtype, AXIS_X, STAT_CLASS_WAYP, stat_id)) { |
395 if (!DrawStationTile(x, y, railtype, AXIS_X, STAT_CLASS_WAYP, stat_id)) { |
442 DrawDefaultWaypointSprite(x, y, railtype); |
396 DrawDefaultWaypointSprite(x, y, railtype); |
443 } |
397 } |
444 } |
398 } |
445 |
399 |
|
400 Waypoint::Waypoint(TileIndex tile) |
|
401 { |
|
402 this->xy = tile; |
|
403 } |
|
404 |
|
405 Waypoint::~Waypoint() |
|
406 { |
|
407 RemoveOrderFromAllVehicles(OT_GOTO_WAYPOINT, this->index); |
|
408 |
|
409 RedrawWaypointSign(this); |
|
410 this->xy = 0; |
|
411 |
|
412 this->QuickFree(); |
|
413 } |
|
414 |
|
415 void Waypoint::QuickFree() |
|
416 { |
|
417 if (this->string != STR_NULL) DeleteName(this->string); |
|
418 } |
|
419 |
|
420 bool Waypoint::IsValid() const |
|
421 { |
|
422 return this->xy != 0; |
|
423 } |
|
424 |
|
425 |
446 /** |
426 /** |
447 * Fix savegames which stored waypoints in their old format |
427 * Fix savegames which stored waypoints in their old format |
448 */ |
428 */ |
449 void FixOldWaypoints() |
429 void FixOldWaypoints() |
450 { |
430 { |
461 } |
441 } |
462 } |
442 } |
463 |
443 |
464 void InitializeWaypoints() |
444 void InitializeWaypoints() |
465 { |
445 { |
466 CleanPool(&_Waypoint_pool); |
446 _Waypoint_pool.CleanPool(); |
467 AddBlockToPool(&_Waypoint_pool); |
447 _Waypoint_pool.AddBlockToPool(); |
468 } |
448 } |
469 |
449 |
470 static const SaveLoad _waypoint_desc[] = { |
450 static const SaveLoad _waypoint_desc[] = { |
471 SLE_CONDVAR(Waypoint, xy, SLE_FILE_U16 | SLE_VAR_U32, 0, 5), |
451 SLE_CONDVAR(Waypoint, xy, SLE_FILE_U16 | SLE_VAR_U32, 0, 5), |
472 SLE_CONDVAR(Waypoint, xy, SLE_UINT32, 6, SL_MAX_VERSION), |
452 SLE_CONDVAR(Waypoint, xy, SLE_UINT32, 6, SL_MAX_VERSION), |
496 static void Load_WAYP() |
476 static void Load_WAYP() |
497 { |
477 { |
498 int index; |
478 int index; |
499 |
479 |
500 while ((index = SlIterateArray()) != -1) { |
480 while ((index = SlIterateArray()) != -1) { |
501 Waypoint *wp; |
481 Waypoint *wp = new (index) Waypoint(); |
502 |
|
503 if (!AddBlockIfNeeded(&_Waypoint_pool, index)) |
|
504 error("Waypoints: failed loading savegame: too many waypoints"); |
|
505 |
|
506 wp = GetWaypoint(index); |
|
507 SlObject(wp, _waypoint_desc); |
482 SlObject(wp, _waypoint_desc); |
508 } |
483 } |
509 } |
484 } |
510 |
485 |
511 extern const ChunkHandler _waypoint_chunk_handlers[] = { |
486 extern const ChunkHandler _waypoint_chunk_handlers[] = { |