~ubuntu-branches/debian/squeeze/openttd/squeeze

« back to all changes in this revision

Viewing changes to src/waypoint.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jordi Mallach, Matthijs Kooijman, Jordi Mallach
  • Date: 2009-04-15 18:22:10 UTC
  • mfrom: (1.1.6 upstream) (2.1.3 squeeze)
  • Revision ID: james.westby@ubuntu.com-20090415182210-22ktb8kdbp2tf3bm
[ Matthijs Kooijman ]
* New upstream release.
* Remove Debian specific desktop file, upstream provides one now. 
* Add debian/watch file.

[ Jordi Mallach ]
* Bump Standards-Version to 3.8.1, with no changes required.
* Move to debhelper compat 7. Bump Build-Depends accordingly.
* Use dh_prep.
* Add "set -e" to config script.
* Remove a few extra doc files that get installed by upstream Makefile.
* Add more complete copyright information.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* $Id: waypoint.cpp 14347 2008-09-16 20:29:09Z rubidium $ */
 
1
/* $Id: waypoint.cpp 15704 2009-03-13 23:48:07Z smatz $ */
2
2
 
3
 
/** @file waypoint.cpp */
 
3
/** @file waypoint.cpp Handling of waypoints. */
4
4
 
5
5
#include "stdafx.h"
6
 
#include "openttd.h"
7
6
 
8
 
#include "command_func.h"
9
 
#include "landscape.h"
10
 
#include "order.h"
11
 
#include "rail_map.h"
 
7
#include "strings_type.h"
12
8
#include "rail.h"
13
 
#include "bridge_map.h"
14
 
#include "saveload.h"
15
 
#include "station.h"
 
9
#include "station_base.h"
16
10
#include "town.h"
17
11
#include "waypoint.h"
18
 
#include "variables.h"
19
 
#include "yapf/yapf.h"
20
 
#include "newgrf.h"
21
 
#include "strings_func.h"
22
 
#include "gfx_func.h"
23
 
#include "functions.h"
24
12
#include "window_func.h"
25
 
#include "economy_func.h"
26
 
#include "date_func.h"
27
 
#include "vehicle_func.h"
28
 
#include "vehicle_base.h"
29
 
#include "string_func.h"
30
 
#include "signal_func.h"
31
 
#include "player_func.h"
32
 
#include "settings_type.h"
33
 
 
34
 
#include "table/strings.h"
 
13
#include "newgrf_station.h"
 
14
#include "oldpool_func.h"
 
15
#include "order_func.h"
35
16
 
36
17
DEFINE_OLD_POOL_GENERIC(Waypoint, Waypoint)
37
18
 
38
 
 
39
 
/**
40
 
 * Update the sign for the waypoint
41
 
 * @param wp Waypoint to update sign */
42
 
static void UpdateWaypointSign(Waypoint* wp)
43
 
{
44
 
        Point pt = RemapCoords2(TileX(wp->xy) * TILE_SIZE, TileY(wp->xy) * TILE_SIZE);
45
 
        SetDParam(0, wp->index);
46
 
        UpdateViewportSignPos(&wp->sign, pt.x, pt.y - 0x20, STR_WAYPOINT_VIEWPORT);
47
 
}
48
 
 
49
 
/**
50
 
 * Redraw the sign of a waypoint
51
 
 * @param wp Waypoint to redraw sign */
52
 
static void RedrawWaypointSign(const Waypoint* wp)
53
 
{
54
 
        MarkAllViewportsDirty(
55
 
                wp->sign.left - 6,
56
 
                wp->sign.top,
57
 
                wp->sign.left + (wp->sign.width_1 << 2) + 12,
58
 
                wp->sign.top + 48);
59
 
}
60
 
 
61
19
/**
62
20
 * Update all signs
63
21
 */
71
29
}
72
30
 
73
31
/**
74
 
 * Set the default name for a waypoint
75
 
 * @param wp Waypoint to work on
76
 
 */
77
 
static void MakeDefaultWaypointName(Waypoint* wp)
78
 
{
79
 
        uint32 used = 0; // bitmap of used waypoint numbers, sliding window with 'next' as base
80
 
        uint32 next = 0; // first waypoint number in the bitmap
81
 
        WaypointID idx = 0; // index where we will stop
82
 
 
83
 
        wp->town_index = ClosestTownFromTile(wp->xy, (uint)-1)->index;
84
 
 
85
 
        /* Find first unused waypoint number belonging to this town. This can never fail,
86
 
         * as long as there can be at most 65535 waypoints in total.
87
 
         *
88
 
         * This does 'n * m' search, but with 32bit 'used' bitmap, it needs at most 'n * (1 + ceil(m / 32))'
89
 
         * steps (n - number of waypoints in pool, m - number of waypoints near this town).
90
 
         * Usually, it needs only 'n' steps.
91
 
         *
92
 
         * If it wasn't using 'used' and 'idx', it would just search for increasing 'next',
93
 
         * but this way it is faster */
94
 
 
95
 
        WaypointID cid = 0; // current index, goes to GetWaypointPoolSize()-1, then wraps to 0
96
 
        do {
97
 
                Waypoint *lwp = GetWaypoint(cid);
98
 
 
99
 
                /* check only valid waypoints... */
100
 
                if (lwp->IsValid() && wp != lwp) {
101
 
                        /* only waypoints with 'generic' name within the same city */
102
 
                        if (lwp->name == NULL && lwp->town_index == wp->town_index) {
103
 
                                /* if lwp->town_cn < next, uint will overflow to '+inf' */
104
 
                                uint i = (uint)lwp->town_cn - next;
105
 
 
106
 
                                if (i < 32) {
107
 
                                        SetBit(used, i); // update bitmap
108
 
                                        if (i == 0) {
109
 
                                                /* shift bitmap while the lowest bit is '1';
110
 
                                                 * increase the base of the bitmap too */
111
 
                                                do {
112
 
                                                        used >>= 1;
113
 
                                                        next++;
114
 
                                                } while (HasBit(used, 0));
115
 
                                                /* when we are at 'idx' again at end of the loop and
116
 
                                                 * 'next' hasn't changed, then no waypoint had town_cn == next,
117
 
                                                 * so we can safely use it */
118
 
                                                idx = cid;
119
 
                                        }
120
 
                                }
121
 
                        }
122
 
                }
123
 
 
124
 
                cid++;
125
 
                if (cid == GetWaypointPoolSize()) cid = 0; // wrap to zero...
126
 
        } while (cid != idx);
127
 
 
128
 
        wp->town_cn = (uint16)next; // set index...
129
 
        wp->name = NULL; // ... and use generic name
130
 
}
131
 
 
132
 
/**
133
 
 * Find a deleted waypoint close to a tile.
134
 
 * @param tile to search from
135
 
 */
136
 
static Waypoint *FindDeletedWaypointCloseTo(TileIndex tile)
137
 
{
138
 
        Waypoint *wp, *best = NULL;
139
 
        uint thres = 8;
140
 
 
141
 
        FOR_ALL_WAYPOINTS(wp) {
142
 
                if (wp->deleted) {
143
 
                        uint cur_dist = DistanceManhattan(tile, wp->xy);
144
 
 
145
 
                        if (cur_dist < thres) {
146
 
                                thres = cur_dist;
147
 
                                best = wp;
148
 
                        }
149
 
                }
150
 
        }
151
 
 
152
 
        return best;
153
 
}
154
 
 
155
 
/**
156
 
 * Update waypoint graphics id against saved GRFID/localidx.
157
 
 * This is to ensure the chosen graphics are correct if GRF files are changed.
158
 
 */
159
 
void AfterLoadWaypoints()
160
 
{
161
 
        Waypoint *wp;
162
 
 
163
 
        FOR_ALL_WAYPOINTS(wp) {
164
 
                uint i;
165
 
 
166
 
                if (wp->grfid == 0) continue;
167
 
 
168
 
                for (i = 0; i < GetNumCustomStations(STAT_CLASS_WAYP); i++) {
169
 
                        const StationSpec *statspec = GetCustomStationSpec(STAT_CLASS_WAYP, i);
170
 
                        if (statspec != NULL && statspec->grffile->grfid == wp->grfid && statspec->localidx == wp->localidx) {
171
 
                                wp->stat_id = i;
172
 
                                break;
173
 
                        }
174
 
                }
175
 
        }
176
 
}
177
 
 
178
 
/** Convert existing rail to waypoint. Eg build a waypoint station over
179
 
 * piece of rail
180
 
 * @param tile tile where waypoint will be built
181
 
 * @param flags type of operation
182
 
 * @param p1 graphics for waypoint type, 0 indicates standard graphics
183
 
 * @param p2 unused
184
 
 *
185
 
 * @todo When checking for the tile slope,
186
 
 * distingush between "Flat land required" and "land sloped in wrong direction"
187
 
 */
188
 
CommandCost CmdBuildTrainWaypoint(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
189
 
{
190
 
        Waypoint *wp;
191
 
        Slope tileh;
192
 
        Axis axis;
193
 
 
194
 
        /* if custom gfx are used, make sure it is within bounds */
195
 
        if (p1 >= GetNumCustomStations(STAT_CLASS_WAYP)) return CMD_ERROR;
196
 
 
197
 
        if (!IsTileType(tile, MP_RAILWAY) ||
198
 
                        GetRailTileType(tile) != RAIL_TILE_NORMAL || (
199
 
                                (axis = AXIS_X, GetTrackBits(tile) != TRACK_BIT_X) &&
200
 
                                (axis = AXIS_Y, GetTrackBits(tile) != TRACK_BIT_Y)
201
 
                        )) {
202
 
                return_cmd_error(STR_1005_NO_SUITABLE_RAILROAD_TRACK);
203
 
        }
204
 
 
205
 
        if (!CheckTileOwnership(tile)) return CMD_ERROR;
206
 
        if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR;
207
 
 
208
 
        tileh = GetTileSlope(tile, NULL);
209
 
        if (tileh != SLOPE_FLAT &&
210
 
                        (!_patches.build_on_slopes || IsSteepSlope(tileh) || !(tileh & (0x3 << axis)) || !(tileh & ~(0x3 << axis)))) {
211
 
                return_cmd_error(STR_0007_FLAT_LAND_REQUIRED);
212
 
        }
213
 
 
214
 
        if (MayHaveBridgeAbove(tile) && IsBridgeAbove(tile)) return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST);
215
 
 
216
 
        /* Check if there is an already existing, deleted, waypoint close to us that we can reuse. */
217
 
        wp = FindDeletedWaypointCloseTo(tile);
218
 
        if (wp == NULL && !Waypoint::CanAllocateItem()) return CMD_ERROR;
219
 
 
220
 
        if (flags & DC_EXEC) {
221
 
                if (wp == NULL) {
222
 
                        wp = new Waypoint(tile);
223
 
 
224
 
                        wp->town_index = INVALID_TOWN;
225
 
                        wp->name = NULL;
226
 
                        wp->town_cn = 0;
227
 
                } else {
228
 
                        /* Move existing (recently deleted) waypoint to the new location */
229
 
 
230
 
                        /* First we update the destination for all vehicles that
231
 
                        * have the old waypoint in their orders. */
232
 
                        Vehicle *v;
233
 
                        FOR_ALL_VEHICLES(v) {
234
 
                                if (v->type == VEH_TRAIN &&
235
 
                                                v->First() == v &&
236
 
                                                v->current_order.type == OT_GOTO_WAYPOINT &&
237
 
                                                v->dest_tile == wp->xy) {
238
 
                                        v->dest_tile = tile;
239
 
                                }
240
 
                        }
241
 
 
242
 
                        RedrawWaypointSign(wp);
243
 
                        wp->xy = tile;
244
 
                }
245
 
 
246
 
                const StationSpec* statspec;
247
 
 
248
 
                MakeRailWaypoint(tile, GetTileOwner(tile), axis, GetRailType(tile), wp->index);
249
 
                MarkTileDirtyByTile(tile);
250
 
 
251
 
                statspec = GetCustomStationSpec(STAT_CLASS_WAYP, p1);
252
 
 
253
 
                if (statspec != NULL) {
254
 
                        wp->stat_id = p1;
255
 
                        wp->grfid = statspec->grffile->grfid;
256
 
                        wp->localidx = statspec->localidx;
257
 
                } else {
258
 
                        /* Specified custom graphics do not exist, so use default. */
259
 
                        wp->stat_id = 0;
260
 
                        wp->grfid = 0;
261
 
                        wp->localidx = 0;
262
 
                }
263
 
 
264
 
                wp->deleted = 0;
265
 
                wp->build_date = _date;
266
 
 
267
 
                if (wp->town_index == INVALID_TOWN) MakeDefaultWaypointName(wp);
268
 
 
269
 
                UpdateWaypointSign(wp);
270
 
                RedrawWaypointSign(wp);
271
 
                YapfNotifyTrackLayoutChange(tile, AxisToTrack(axis));
272
 
        }
273
 
 
274
 
        return CommandCost(EXPENSES_CONSTRUCTION, _price.build_train_depot);
275
 
}
276
 
 
277
 
/**
278
32
 * Daily loop for waypoints
279
33
 */
280
34
void WaypointsDailyLoop()
288
42
}
289
43
 
290
44
/**
291
 
 * Remove a waypoint
292
 
 * @param tile from which to remove waypoint
293
 
 * @param flags type of operation
294
 
 * @param justremove will indicate if it is removed from rail or if rails are removed too
295
 
 * @return cost of operation or error
296
 
 */
297
 
CommandCost RemoveTrainWaypoint(TileIndex tile, uint32 flags, bool justremove)
298
 
{
299
 
        Waypoint *wp;
300
 
 
301
 
        /* Make sure it's a waypoint */
302
 
        if (!IsTileType(tile, MP_RAILWAY) ||
303
 
                        !IsRailWaypoint(tile) ||
304
 
                        (!CheckTileOwnership(tile) && _current_player != OWNER_WATER) ||
305
 
                        !EnsureNoVehicleOnGround(tile)) {
306
 
                return CMD_ERROR;
307
 
        }
308
 
 
309
 
        if (flags & DC_EXEC) {
310
 
                Track track = GetRailWaypointTrack(tile);
311
 
                Owner owner = GetTileOwner(tile); // cannot use _current_player because of possible floods
312
 
                wp = GetWaypointByTile(tile);
313
 
 
314
 
                wp->deleted = 30; // let it live for this many days before we do the actual deletion.
315
 
                RedrawWaypointSign(wp);
316
 
 
317
 
                if (justremove) {
318
 
                        MakeRailNormal(tile, GetTileOwner(tile), GetRailWaypointBits(tile), GetRailType(tile));
319
 
                        MarkTileDirtyByTile(tile);
320
 
                } else {
321
 
                        DoClearSquare(tile);
322
 
                        AddTrackToSignalBuffer(tile, track, owner);
323
 
                }
324
 
                YapfNotifyTrackLayoutChange(tile, track);
325
 
        }
326
 
 
327
 
        return CommandCost(EXPENSES_CONSTRUCTION, _price.remove_train_depot);
328
 
}
329
 
 
330
 
/**
331
 
 * Delete a waypoint
332
 
 * @param tile tile where waypoint is to be deleted
333
 
 * @param flags type of operation
334
 
 * @param p1 unused
335
 
 * @param p2 unused
336
 
 * @return cost of operation or error
337
 
 */
338
 
CommandCost CmdRemoveTrainWaypoint(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
339
 
{
340
 
        return RemoveTrainWaypoint(tile, flags, true);
341
 
}
342
 
 
343
 
static bool IsUniqueWaypointName(const char *name)
344
 
{
345
 
        const Waypoint *wp;
346
 
        char buf[512];
347
 
 
348
 
        FOR_ALL_WAYPOINTS(wp) {
349
 
                SetDParam(0, wp->index);
350
 
                GetString(buf, STR_WAYPOINT_RAW, lastof(buf));
351
 
                if (strcmp(buf, name) == 0) return false;
352
 
        }
353
 
 
354
 
        return true;
355
 
}
356
 
 
357
 
/**
358
 
 * Rename a waypoint.
359
 
 * @param tile unused
360
 
 * @param flags type of operation
361
 
 * @param p1 id of waypoint
362
 
 * @param p2 unused
363
 
 * @return cost of operation or error
364
 
 */
365
 
CommandCost CmdRenameWaypoint(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
366
 
{
367
 
        Waypoint *wp;
368
 
 
369
 
        if (!IsValidWaypointID(p1)) return CMD_ERROR;
370
 
 
371
 
        wp = GetWaypoint(p1);
372
 
        if (!IsTileType(wp->xy, MP_RAILWAY) || !CheckTileOwnership(wp->xy)) return CMD_ERROR;
373
 
 
374
 
        if (!StrEmpty(_cmd_text)) {
375
 
                if (!IsUniqueWaypointName(_cmd_text)) return_cmd_error(STR_NAME_MUST_BE_UNIQUE);
376
 
 
377
 
                if (flags & DC_EXEC) {
378
 
                        free(wp->name);
379
 
                        wp->name = strdup(_cmd_text);
380
 
                        wp->town_cn = 0;
381
 
 
382
 
                        UpdateWaypointSign(wp);
383
 
                        MarkWholeScreenDirty();
384
 
                }
385
 
        } else {
386
 
                if (flags & DC_EXEC) {
387
 
                        free(wp->name);
388
 
 
389
 
                        MakeDefaultWaypointName(wp);
390
 
                        UpdateWaypointSign(wp);
391
 
                        MarkWholeScreenDirty();
392
 
                }
393
 
        }
394
 
        return CommandCost();
395
 
}
396
 
 
397
 
/**
398
45
 * This hacks together some dummy one-shot Station structure for a waypoint.
399
46
 * @param tile on which to work
400
47
 * @return pointer to a Station
442
89
        free(this->name);
443
90
 
444
91
        if (CleaningPool()) return;
445
 
 
 
92
        DeleteWindowById(WC_WAYPOINT_VIEW, this->index);
446
93
        RemoveOrderFromAllVehicles(OT_GOTO_WAYPOINT, this->index);
447
94
 
448
95
        RedrawWaypointSign(this);
449
 
        this->xy = 0;
450
 
}
451
 
 
452
 
/**
453
 
 * Fix savegames which stored waypoints in their old format
454
 
 */
455
 
void FixOldWaypoints()
456
 
{
457
 
        Waypoint *wp;
458
 
 
459
 
        /* Convert the old 'town_or_string', to 'string' / 'town' / 'town_cn' */
460
 
        FOR_ALL_WAYPOINTS(wp) {
461
 
                wp->town_index = ClosestTownFromTile(wp->xy, (uint)-1)->index;
462
 
                wp->town_cn = 0;
463
 
                if (wp->string & 0xC000) {
464
 
                        wp->town_cn = wp->string & 0x3F;
465
 
                        wp->string = STR_NULL;
466
 
                }
467
 
        }
 
96
        this->xy = INVALID_TILE;
468
97
}
469
98
 
470
99
void InitializeWaypoints()
472
101
        _Waypoint_pool.CleanPool();
473
102
        _Waypoint_pool.AddBlockToPool();
474
103
}
475
 
 
476
 
static const SaveLoad _waypoint_desc[] = {
477
 
        SLE_CONDVAR(Waypoint, xy,         SLE_FILE_U16 | SLE_VAR_U32,  0, 5),
478
 
        SLE_CONDVAR(Waypoint, xy,         SLE_UINT32,                  6, SL_MAX_VERSION),
479
 
        SLE_CONDVAR(Waypoint, town_index, SLE_UINT16,                 12, SL_MAX_VERSION),
480
 
        SLE_CONDVAR(Waypoint, town_cn,    SLE_FILE_U8 | SLE_VAR_U16,  12, 88),
481
 
        SLE_CONDVAR(Waypoint, town_cn,    SLE_UINT16,                 89, SL_MAX_VERSION),
482
 
        SLE_CONDVAR(Waypoint, string,     SLE_STRINGID,                0, 83),
483
 
        SLE_CONDSTR(Waypoint, name,       SLE_STR, 0,                 84, SL_MAX_VERSION),
484
 
            SLE_VAR(Waypoint, deleted,    SLE_UINT8),
485
 
 
486
 
        SLE_CONDVAR(Waypoint, build_date, SLE_FILE_U16 | SLE_VAR_I32,  3, 30),
487
 
        SLE_CONDVAR(Waypoint, build_date, SLE_INT32,                  31, SL_MAX_VERSION),
488
 
        SLE_CONDVAR(Waypoint, localidx,   SLE_UINT8,                   3, SL_MAX_VERSION),
489
 
        SLE_CONDVAR(Waypoint, grfid,      SLE_UINT32,                 17, SL_MAX_VERSION),
490
 
 
491
 
        SLE_END()
492
 
};
493
 
 
494
 
static void Save_WAYP()
495
 
{
496
 
        Waypoint *wp;
497
 
 
498
 
        FOR_ALL_WAYPOINTS(wp) {
499
 
                SlSetArrayIndex(wp->index);
500
 
                SlObject(wp, _waypoint_desc);
501
 
        }
502
 
}
503
 
 
504
 
static void Load_WAYP()
505
 
{
506
 
        int index;
507
 
 
508
 
        while ((index = SlIterateArray()) != -1) {
509
 
                Waypoint *wp = new (index) Waypoint();
510
 
                SlObject(wp, _waypoint_desc);
511
 
        }
512
 
}
513
 
 
514
 
extern const ChunkHandler _waypoint_chunk_handlers[] = {
515
 
        { 'CHKP', Save_WAYP, Load_WAYP, CH_ARRAY | CH_LAST},
516
 
};