author | bjarni |
Thu, 09 Dec 2004 21:46:56 +0000 | |
changeset 578 | 86e352980acd |
parent 555 | eec6c0294435 |
child 588 | 1b60458bdc29 |
permissions | -rw-r--r-- |
0 | 1 |
#include "stdafx.h" |
2 |
#include "ttd.h" |
|
507
8aa8100b0b22
(svn r815) Include strings.h only in the files which need it.
tron
parents:
445
diff
changeset
|
3 |
#include "table/strings.h" |
0 | 4 |
#include "vehicle.h" |
5 |
#include "command.h" |
|
6 |
#include "pathfind.h" |
|
7 |
#include "station.h" |
|
8 |
#include "gfx.h" |
|
9 |
#include "news.h" |
|
10 |
#include "engine.h" |
|
11 |
#include "gui.h" |
|
12 |
#include "player.h" |
|
337
66647f97e7c0
(svn r513) Merge revisions 402, 416, 417, 478, 479, 511, 512 from map to trunk
tron
parents:
297
diff
changeset
|
13 |
#include "sound.h" |
0 | 14 |
|
15 |
static const uint16 _ship_sprites[] = {0x0E5D, 0x0E55, 0x0E65, 0x0E6D}; |
|
16 |
static const byte _ship_sometracks[4] = {0x19, 0x16, 0x25, 0x2A}; |
|
17 |
||
18 |
static byte GetTileShipTrackStatus(uint tile) { |
|
159
139cf78bfb28
(svn r160) -Codechange: made GetTileTrackStatus more readable (blathijs)
truelight
parents:
156
diff
changeset
|
19 |
uint32 r = GetTileTrackStatus(tile, TRANSPORT_WATER); |
0 | 20 |
return r | r >> 8; |
21 |
} |
|
22 |
||
23 |
void DrawShipEngine(int x, int y, int engine, uint32 image_ormod) |
|
24 |
{ |
|
538
5dd99f3b7eca
(svn r920) Replace vehicle info macros with inline functions and add asserts to check limits
tron
parents:
534
diff
changeset
|
25 |
int spritenum = ShipVehInfo(engine)->image_index; |
0 | 26 |
|
27 |
if (is_custom_sprite(spritenum)) { |
|
358
6eb0d5ec99b1
(svn r546) -newgrf: Use GetCustomVehicleIcon() for fetching sprites for vehicle selection dialogs. (Idea by octo, done by pasky).
darkvater
parents:
337
diff
changeset
|
28 |
int sprite = GetCustomVehicleIcon(engine, 6); |
0 | 29 |
|
30 |
if (sprite) { |
|
31 |
DrawSprite(sprite | image_ormod, x, y); |
|
32 |
return; |
|
33 |
} |
|
34 |
spritenum = _engine_original_sprites[engine]; |
|
35 |
} |
|
36 |
DrawSprite((6 + _ship_sprites[spritenum]) | image_ormod, x, y); |
|
37 |
} |
|
38 |
||
39 |
void DrawShipEngineInfo(int engine, int x, int y, int maxw) |
|
40 |
{ |
|
538
5dd99f3b7eca
(svn r920) Replace vehicle info macros with inline functions and add asserts to check limits
tron
parents:
534
diff
changeset
|
41 |
const ShipVehicleInfo *svi = ShipVehInfo(engine); |
534
17ab2f22ff74
(svn r901) Small step in the process to clean up the DPARAM mess:
tron
parents:
507
diff
changeset
|
42 |
SetDParam(0, svi->base_cost * (_price.ship_base>>3)>>5); |
17ab2f22ff74
(svn r901) Small step in the process to clean up the DPARAM mess:
tron
parents:
507
diff
changeset
|
43 |
SetDParam(1, svi->max_speed * 10 >> 5); |
17ab2f22ff74
(svn r901) Small step in the process to clean up the DPARAM mess:
tron
parents:
507
diff
changeset
|
44 |
SetDParam(2, _cargoc.names_long_p[svi->cargo_type]); |
17ab2f22ff74
(svn r901) Small step in the process to clean up the DPARAM mess:
tron
parents:
507
diff
changeset
|
45 |
SetDParam(3, svi->capacity); |
17ab2f22ff74
(svn r901) Small step in the process to clean up the DPARAM mess:
tron
parents:
507
diff
changeset
|
46 |
SetDParam(4, svi->running_cost * _price.ship_running >> 8); |
0 | 47 |
DrawStringMultiCenter(x, y, STR_982E_COST_MAX_SPEED_CAPACITY, maxw); |
48 |
} |
|
49 |
||
50 |
int GetShipImage(Vehicle *v, byte direction) |
|
51 |
{ |
|
52 |
int spritenum = v->spritenum; |
|
53 |
||
54 |
if (is_custom_sprite(spritenum)) { |
|
55 |
int sprite = GetCustomVehicleSprite(v, direction); |
|
56 |
||
57 |
if (sprite) return sprite; |
|
58 |
spritenum = _engine_original_sprites[v->engine_type]; |
|
59 |
} |
|
60 |
return _ship_sprites[spritenum] + direction; |
|
61 |
} |
|
62 |
||
63 |
static int FindClosestShipDepot(Vehicle *v) |
|
64 |
{ |
|
65 |
uint tile, dist, best_dist = (uint)-1; |
|
66 |
int best_depot = -1; |
|
67 |
int i; |
|
68 |
byte owner = v->owner; |
|
69 |
uint tile2 = v->tile; |
|
70 |
||
71 |
for(i=0; i!=lengthof(_depots); i++) { |
|
72 |
tile = _depots[i].xy; |
|
73 |
if (IS_TILETYPE(tile, MP_WATER) && _map_owner[tile] == owner) { |
|
74 |
dist = GetTileDist(tile, tile2); |
|
75 |
if (dist < best_dist) { |
|
76 |
best_dist = dist; |
|
77 |
best_depot = i; |
|
78 |
} |
|
79 |
} |
|
80 |
} |
|
81 |
||
82 |
return best_depot; |
|
83 |
} |
|
84 |
||
85 |
static void CheckIfShipNeedsService(Vehicle *v) |
|
86 |
{ |
|
87 |
int i; |
|
88 |
||
76
30511cbc5188
(svn r77) -Fix: [1010788] AI service interval bug (tnx truesatan)
truelight
parents:
19
diff
changeset
|
89 |
if (_patches.servint_ships == 0) |
11
836bc4b37b5b
(svn r12) Change: removed patch no_train_service. Instead you can set the default service interval for any vehicle type to 'disabled'.
dominik
parents:
0
diff
changeset
|
90 |
return; |
836bc4b37b5b
(svn r12) Change: removed patch no_train_service. Instead you can set the default service interval for any vehicle type to 'disabled'.
dominik
parents:
0
diff
changeset
|
91 |
|
156
8fef5e5752d6
(svn r157) -Feature: [1009708] Percent-based service intervals. Send a vehicle to depot after it has lost X% of its reliability (mivlad)
darkvater
parents:
76
diff
changeset
|
92 |
if (SERVICE_INTERVAL) |
0 | 93 |
return; |
94 |
||
95 |
if (v->vehstatus & VS_STOPPED) |
|
96 |
return; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
97 |
|
555
eec6c0294435
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
98 |
if (v->current_order.type == OT_GOTO_DEPOT && |
eec6c0294435
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
99 |
v->current_order.flags & OF_FULL_LOAD) |
0 | 100 |
return; |
101 |
||
76
30511cbc5188
(svn r77) -Fix: [1010788] AI service interval bug (tnx truesatan)
truelight
parents:
19
diff
changeset
|
102 |
if (_patches.gotodepot && ScheduleHasDepotOrders(v->schedule_ptr)) |
0 | 103 |
return; |
104 |
||
105 |
i = FindClosestShipDepot(v); |
|
106 |
||
107 |
if (i < 0 || GetTileDist(v->tile, (&_depots[i])->xy) > 12) { |
|
555
eec6c0294435
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
108 |
if (v->current_order.type == OT_GOTO_DEPOT) { |
eec6c0294435
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
109 |
v->current_order.type = OT_DUMMY; |
eec6c0294435
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
110 |
v->current_order.flags = 0; |
0 | 111 |
InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); |
112 |
} |
|
113 |
return; |
|
114 |
} |
|
115 |
||
555
eec6c0294435
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
116 |
v->current_order.type = OT_GOTO_DEPOT; |
eec6c0294435
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
117 |
v->current_order.flags = OF_NON_STOP; |
eec6c0294435
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
118 |
v->current_order.station = (byte)i; |
0 | 119 |
v->dest_tile = (&_depots[i])->xy; |
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
120 |
InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); |
0 | 121 |
} |
122 |
||
123 |
void OnNewDay_Ship(Vehicle *v) |
|
124 |
{ |
|
125 |
int32 cost; |
|
126 |
||
127 |
if ((++v->day_counter & 7) == 0) |
|
128 |
DecreaseVehicleValue(v); |
|
129 |
||
130 |
CheckVehicleBreakdown(v); |
|
131 |
AgeVehicle(v); |
|
132 |
CheckIfShipNeedsService(v); |
|
133 |
||
19
6080d2b6a959
(svn r20) Feature: warning when a vehicle has invalid orders (celestar)
dominik
parents:
11
diff
changeset
|
134 |
CheckOrders(v); |
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
135 |
|
0 | 136 |
if (v->vehstatus & VS_STOPPED) |
137 |
return; |
|
138 |
||
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
139 |
|
19
6080d2b6a959
(svn r20) Feature: warning when a vehicle has invalid orders (celestar)
dominik
parents:
11
diff
changeset
|
140 |
|
538
5dd99f3b7eca
(svn r920) Replace vehicle info macros with inline functions and add asserts to check limits
tron
parents:
534
diff
changeset
|
141 |
cost = ShipVehInfo(v->engine_type)->running_cost * _price.ship_running / 364; |
0 | 142 |
v->profit_this_year -= cost >> 8; |
143 |
||
144 |
SET_EXPENSES_TYPE(EXPENSES_SHIP_RUN); |
|
145 |
SubtractMoneyFromPlayerFract(v->owner, cost); |
|
146 |
||
147 |
InvalidateWindow(WC_VEHICLE_DETAILS, v->index); |
|
148 |
InvalidateWindow(WC_SHIPS_LIST, v->owner); |
|
149 |
} |
|
150 |
||
151 |
static void HandleBrokenShip(Vehicle *v) |
|
152 |
{ |
|
153 |
if (v->breakdown_ctr != 1) { |
|
154 |
v->breakdown_ctr = 1; |
|
155 |
v->cur_speed = 0; |
|
156 |
||
157 |
if (v->breakdowns_since_last_service != 255) |
|
158 |
v->breakdowns_since_last_service++; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
159 |
|
0 | 160 |
InvalidateWindow(WC_VEHICLE_VIEW, v->index); |
161 |
InvalidateWindow(WC_VEHICLE_DETAILS, v->index); |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
162 |
|
541 | 163 |
SndPlayVehicleFx((_opt.landscape != LT_CANDY) ? |
164 |
SND_10_TRAIN_BREAKDOWN : SND_3A_COMEDY_BREAKDOWN_2, v); |
|
0 | 165 |
|
166 |
if (!(v->vehstatus & VS_HIDDEN)) { |
|
167 |
Vehicle *u = CreateEffectVehicleRel(v, 4, 4, 5, EV_BREAKDOWN_SMOKE); |
|
168 |
if (u) |
|
169 |
u->u.special.unk0 = v->breakdown_delay * 2; |
|
170 |
} |
|
171 |
} |
|
172 |
||
173 |
if (!(v->tick_counter & 1)) { |
|
174 |
if (!--v->breakdown_delay) { |
|
175 |
v->breakdown_ctr = 0; |
|
176 |
InvalidateWindow(WC_VEHICLE_VIEW, v->index); |
|
177 |
} |
|
178 |
} |
|
179 |
} |
|
180 |
||
181 |
static void MarkShipDirty(Vehicle *v) |
|
182 |
{ |
|
183 |
v->cur_image = GetShipImage(v, v->direction); |
|
184 |
MarkAllViewportsDirty(v->left_coord, v->top_coord, v->right_coord + 1, v->bottom_coord + 1); |
|
185 |
} |
|
186 |
||
187 |
static void PlayShipSound(Vehicle *v) |
|
188 |
{ |
|
538
5dd99f3b7eca
(svn r920) Replace vehicle info macros with inline functions and add asserts to check limits
tron
parents:
534
diff
changeset
|
189 |
SndPlayVehicleFx(ShipVehInfo(v->engine_type)->sfx, v); |
0 | 190 |
} |
191 |
||
192 |
static const TileIndexDiff _dock_offs[] = { |
|
193 |
TILE_XY(2, 0), |
|
194 |
TILE_XY(-2, 0), |
|
195 |
TILE_XY(0, 2), |
|
196 |
TILE_XY(2, 0), |
|
197 |
TILE_XY(0, -2), |
|
198 |
TILE_XY(0,0), |
|
199 |
TILE_XY(0,0), |
|
200 |
TILE_XY(0,0), |
|
201 |
}; |
|
202 |
||
203 |
static void ProcessShipOrder(Vehicle *v) |
|
204 |
{ |
|
555
eec6c0294435
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
205 |
Order order; |
0 | 206 |
Station *st; |
207 |
||
555
eec6c0294435
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
208 |
if (v->current_order.type >= OT_GOTO_DEPOT && |
eec6c0294435
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
209 |
v->current_order.type <= OT_LEAVESTATION) { |
eec6c0294435
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
210 |
if (v->current_order.type != OT_GOTO_DEPOT || |
eec6c0294435
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
211 |
!(v->current_order.flags & OF_UNLOAD)) |
0 | 212 |
return; |
213 |
} |
|
214 |
||
555
eec6c0294435
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
215 |
if (v->current_order.type == OT_GOTO_DEPOT && |
eec6c0294435
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
216 |
(v->current_order.flags & (OF_UNLOAD | OF_FULL_LOAD)) == (OF_UNLOAD | OF_FULL_LOAD) && |
156
8fef5e5752d6
(svn r157) -Feature: [1009708] Percent-based service intervals. Send a vehicle to depot after it has lost X% of its reliability (mivlad)
darkvater
parents:
76
diff
changeset
|
217 |
SERVICE_INTERVAL) { |
0 | 218 |
v->cur_order_index++; |
219 |
} |
|
220 |
||
221 |
||
222 |
if (v->cur_order_index >= v->num_orders) |
|
223 |
v->cur_order_index = 0; |
|
224 |
||
225 |
order = v->schedule_ptr[v->cur_order_index]; |
|
226 |
||
555
eec6c0294435
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
227 |
if (order.type == OT_NOTHING) { |
eec6c0294435
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
228 |
v->current_order.type = OT_NOTHING; |
eec6c0294435
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
229 |
v->current_order.flags = 0; |
0 | 230 |
v->dest_tile = 0; |
231 |
return; |
|
232 |
} |
|
233 |
||
555
eec6c0294435
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
234 |
if (order.type == v->current_order.type && |
eec6c0294435
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
235 |
order.flags == v->current_order.flags && |
eec6c0294435
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
236 |
order.station == v->current_order.station) |
0 | 237 |
return; |
238 |
||
555
eec6c0294435
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
239 |
v->current_order = order; |
0 | 240 |
|
555
eec6c0294435
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
241 |
if (order.type == OT_GOTO_STATION) { |
eec6c0294435
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
242 |
if (order.station == v->last_station_visited) |
0 | 243 |
v->last_station_visited = 0xFF; |
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
244 |
|
555
eec6c0294435
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
245 |
st = DEREF_STATION(order.station); |
0 | 246 |
if (st->dock_tile != 0) { |
247 |
v->dest_tile = TILE_ADD(st->dock_tile, _dock_offs[_map5[st->dock_tile]-0x4B]); |
|
248 |
} |
|
555
eec6c0294435
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
249 |
} else if (order.type == OT_GOTO_DEPOT) { |
eec6c0294435
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
250 |
v->dest_tile = _depots[order.station].xy; |
0 | 251 |
} else { |
252 |
v->dest_tile = 0; |
|
253 |
} |
|
254 |
InvalidateVehicleOrderWidget(v); |
|
255 |
} |
|
256 |
||
257 |
static void HandleShipLoading(Vehicle *v) |
|
258 |
{ |
|
555
eec6c0294435
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
259 |
if (v->current_order.type == OT_NOTHING) |
0 | 260 |
return; |
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
261 |
|
555
eec6c0294435
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
262 |
if (v->current_order.type != OT_DUMMY) { |
eec6c0294435
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
263 |
if (v->current_order.type != OT_LOADING) |
0 | 264 |
return; |
265 |
||
266 |
if (--v->load_unload_time_rem) |
|
267 |
return; |
|
268 |
||
555
eec6c0294435
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
269 |
if (v->current_order.flags & OF_FULL_LOAD && CanFillVehicle(v)) { |
0 | 270 |
SET_EXPENSES_TYPE(EXPENSES_SHIP_INC); |
271 |
if (LoadUnloadVehicle(v)) { |
|
272 |
InvalidateWindow(WC_SHIPS_LIST, v->owner); |
|
273 |
MarkShipDirty(v); |
|
274 |
} |
|
275 |
return; |
|
276 |
} |
|
277 |
PlayShipSound(v); |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
278 |
|
0 | 279 |
{ |
555
eec6c0294435
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
280 |
Order b = v->current_order; |
eec6c0294435
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
281 |
v->current_order.type = OT_LEAVESTATION; |
eec6c0294435
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
282 |
v->current_order.flags = 0; |
eec6c0294435
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
283 |
if (!(b.flags & OF_NON_STOP)) |
0 | 284 |
return; |
285 |
} |
|
286 |
} |
|
287 |
||
288 |
v->cur_order_index++; |
|
289 |
InvalidateVehicleOrderWidget(v); |
|
290 |
} |
|
291 |
||
292 |
static void UpdateShipDeltaXY(Vehicle *v, int dir) |
|
293 |
{ |
|
294 |
#define MKIT(d,c,b,a) ((a&0xFF)<<24) | ((b&0xFF)<<16) | ((c&0xFF)<<8) | ((d&0xFF)<<0) |
|
295 |
static const uint32 _delta_xy_table[8] = { |
|
296 |
MKIT( -3, -3, 6, 6), |
|
297 |
MKIT(-16, -3, 32, 6), |
|
298 |
MKIT( -3, -3, 6, 6), |
|
299 |
MKIT( -3,-16, 6, 32), |
|
300 |
MKIT( -3, -3, 6, 6), |
|
301 |
MKIT(-16, -3, 32, 6), |
|
302 |
MKIT( -3, -3, 6, 6), |
|
303 |
MKIT( -3,-16, 6, 32), |
|
304 |
}; |
|
305 |
#undef MKIT |
|
306 |
uint32 x = _delta_xy_table[dir]; |
|
307 |
v->x_offs = (byte)x; |
|
308 |
v->y_offs = (byte)(x>>=8); |
|
309 |
v->sprite_width = (byte)(x>>=8); |
|
310 |
v->sprite_height = (byte)(x>>=8); |
|
311 |
} |
|
312 |
||
313 |
static void RecalcShipStuff(Vehicle *v) |
|
314 |
{ |
|
315 |
UpdateShipDeltaXY(v, v->direction); |
|
316 |
v->cur_image = GetShipImage(v, v->direction); |
|
317 |
MarkShipDirty(v); |
|
318 |
InvalidateWindow(WC_VEHICLE_DEPOT, v->tile); |
|
319 |
} |
|
320 |
||
321 |
static const TileIndexDiff _ship_leave_depot_offs[] = { |
|
322 |
TILE_XY(-1,0), |
|
323 |
TILE_XY(0,-1), |
|
324 |
}; |
|
325 |
||
326 |
static void CheckShipLeaveDepot(Vehicle *v) |
|
327 |
{ |
|
328 |
uint tile; |
|
329 |
int d; |
|
330 |
uint m; |
|
331 |
||
332 |
if (v->u.ship.state != 0x80) |
|
333 |
return; |
|
334 |
||
335 |
tile = v->tile; |
|
336 |
d = (_map5[tile]&2) ? 1 : 0; |
|
337 |
||
338 |
// Check first side |
|
339 |
if (_ship_sometracks[d] & GetTileShipTrackStatus(TILE_ADD(tile,_ship_leave_depot_offs[d]))) { |
|
340 |
m = (d==0) ? 0x101 : 0x207; |
|
341 |
// Check second side |
|
342 |
} else if (_ship_sometracks[d+2] & GetTileShipTrackStatus(TILE_ADD(tile, -2*_ship_leave_depot_offs[d]))) { |
|
343 |
m = (d==0) ? 0x105 : 0x203; |
|
344 |
} else { |
|
345 |
return; |
|
346 |
} |
|
347 |
v->direction = (byte)m; |
|
348 |
v->u.ship.state = (byte)(m >> 8); |
|
349 |
v->vehstatus &= ~VS_HIDDEN; |
|
350 |
||
351 |
v->cur_speed = 0; |
|
352 |
RecalcShipStuff(v); |
|
353 |
||
354 |
PlayShipSound(v); |
|
578
86e352980acd
(svn r998) now vehicles are serviced both when entering and when leaving depots to prevent that vehicles might need service when leaving after a long stay (ln--)
bjarni
parents:
555
diff
changeset
|
355 |
VehicleServiceInDepot(v); |
0 | 356 |
} |
357 |
||
358 |
static bool ShipAccelerate(Vehicle *v) |
|
359 |
{ |
|
360 |
uint spd; |
|
361 |
byte t; |
|
362 |
||
363 |
spd = min(v->cur_speed + 1, v->max_speed); |
|
364 |
||
365 |
//updates statusbar only if speed have changed to save CPU time |
|
366 |
if (spd != v->cur_speed) { |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
367 |
v->cur_speed = spd; |
0 | 368 |
if (_patches.vehicle_speed) |
369 |
InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); |
|
370 |
} |
|
371 |
||
372 |
// Decrease somewhat when turning |
|
373 |
if (!(v->direction&1)) { |
|
374 |
spd = spd * 3 >> 2; |
|
375 |
} |
|
376 |
||
377 |
if (spd == 0) |
|
378 |
return false; |
|
379 |
||
380 |
if ((byte)++spd == 0) |
|
381 |
return true; |
|
382 |
||
383 |
v->progress = (t = v->progress) - (byte)spd; |
|
384 |
||
385 |
return (t < v->progress); |
|
386 |
} |
|
387 |
||
388 |
||
389 |
static int32 EstimateShipCost(uint16 engine_type); |
|
390 |
||
391 |
static void ShipEnterDepot(Vehicle *v) |
|
392 |
{ |
|
393 |
v->u.ship.state = 0x80; |
|
394 |
v->vehstatus |= VS_HIDDEN; |
|
395 |
v->cur_speed = 0; |
|
396 |
RecalcShipStuff(v); |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
397 |
|
578
86e352980acd
(svn r998) now vehicles are serviced both when entering and when leaving depots to prevent that vehicles might need service when leaving after a long stay (ln--)
bjarni
parents:
555
diff
changeset
|
398 |
VehicleServiceInDepot(v); |
86e352980acd
(svn r998) now vehicles are serviced both when entering and when leaving depots to prevent that vehicles might need service when leaving after a long stay (ln--)
bjarni
parents:
555
diff
changeset
|
399 |
|
0 | 400 |
InvalidateWindow(WC_VEHICLE_DETAILS, v->index); |
401 |
||
402 |
MaybeRenewVehicle(v, EstimateShipCost(v->engine_type)); |
|
403 |
||
445
0e3fa3da3899
(svn r654) Hopefully complete support for randomized variational spritegroups (i.e. the cars transporter in DBSetXL gets different cars each time) (pasky)
tron
parents:
410
diff
changeset
|
404 |
TriggerVehicle(v, VEHICLE_TRIGGER_DEPOT); |
0e3fa3da3899
(svn r654) Hopefully complete support for randomized variational spritegroups (i.e. the cars transporter in DBSetXL gets different cars each time) (pasky)
tron
parents:
410
diff
changeset
|
405 |
|
555
eec6c0294435
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
406 |
if (v->current_order.type == OT_GOTO_DEPOT) { |
eec6c0294435
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
407 |
Order t; |
eec6c0294435
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
408 |
|
0 | 409 |
InvalidateWindow(WC_VEHICLE_VIEW, v->index); |
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
410 |
|
555
eec6c0294435
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
411 |
t = v->current_order; |
eec6c0294435
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
412 |
v->current_order.type = OT_DUMMY; |
eec6c0294435
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
413 |
v->current_order.flags = 0; |
0 | 414 |
|
555
eec6c0294435
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
415 |
if (t.flags & OF_UNLOAD) { |
eec6c0294435
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
416 |
v->cur_order_index++; |
eec6c0294435
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
417 |
} else if (t.flags & OF_FULL_LOAD) { |
0 | 418 |
v->vehstatus |= VS_STOPPED; |
419 |
if (v->owner == _local_player) { |
|
534
17ab2f22ff74
(svn r901) Small step in the process to clean up the DPARAM mess:
tron
parents:
507
diff
changeset
|
420 |
SetDParam(0, v->unitnumber); |
0 | 421 |
AddNewsItem( |
422 |
STR_981C_SHIP_IS_WAITING_IN_DEPOT, |
|
423 |
NEWS_FLAGS(NM_SMALL, NF_VIEWPORT|NF_VEHICLE, NT_ADVICE, 0), |
|
424 |
v->index, |
|
425 |
0); |
|
426 |
} |
|
427 |
} |
|
428 |
} |
|
429 |
} |
|
430 |
||
431 |
static void ShipArrivesAt(Vehicle *v, Station *st) |
|
432 |
{ |
|
433 |
/* Check if station was ever visited before */ |
|
434 |
if (!(st->had_vehicle_of_type & HVOT_SHIP)) { |
|
435 |
uint32 flags; |
|
436 |
st->had_vehicle_of_type |= HVOT_SHIP; |
|
534
17ab2f22ff74
(svn r901) Small step in the process to clean up the DPARAM mess:
tron
parents:
507
diff
changeset
|
437 |
SetDParam(0, st->index); |
0 | 438 |
flags = (v->owner == _local_player) ? NEWS_FLAGS(NM_THIN, NF_VIEWPORT|NF_VEHICLE, NT_ARRIVAL_PLAYER, 0) : NEWS_FLAGS(NM_THIN, NF_VIEWPORT|NF_VEHICLE, NT_ARRIVAL_OTHER, 0); |
439 |
AddNewsItem( |
|
440 |
STR_9833_CITIZENS_CELEBRATE_FIRST, |
|
441 |
flags, |
|
442 |
v->index, |
|
443 |
0); |
|
444 |
} |
|
445 |
} |
|
446 |
||
447 |
typedef struct { |
|
448 |
uint skiptile; |
|
449 |
uint dest_coords; |
|
450 |
uint best_bird_dist; |
|
451 |
uint best_length; |
|
452 |
} PathFindShip; |
|
453 |
||
454 |
//extern void dbg_store_path(); |
|
455 |
||
456 |
static bool ShipTrackFollower(uint tile, PathFindShip *pfs, int track, uint length, byte *state) |
|
457 |
{ |
|
458 |
// Found dest? |
|
459 |
if (tile == pfs->dest_coords) { |
|
460 |
pfs->best_bird_dist = 0; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
461 |
|
0 | 462 |
// if (length < pfs->best_length) |
463 |
// dbg_store_path(); |
|
464 |
||
465 |
pfs->best_length = minu(pfs->best_length, length); |
|
466 |
return true; |
|
467 |
} |
|
468 |
||
469 |
// Skip this tile in the calculation |
|
470 |
if (tile != pfs->skiptile) { |
|
471 |
pfs->best_bird_dist = minu(pfs->best_bird_dist, GetTileDist1Db(pfs->dest_coords, tile)); |
|
472 |
} |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
473 |
|
0 | 474 |
return false; |
475 |
} |
|
476 |
||
477 |
static const byte _ship_search_directions[6][4] = { |
|
478 |
{ 0, 9, 2, 9 }, |
|
479 |
{ 9, 1, 9, 3 }, |
|
480 |
{ 9, 0, 3, 9 }, |
|
481 |
{ 1, 9, 9, 2 }, |
|
482 |
{ 3, 2, 9, 9 }, |
|
483 |
{ 9, 9, 1, 0 }, |
|
484 |
}; |
|
485 |
||
486 |
static const byte _pick_shiptrack_table[6] = {1, 3, 2, 2, 0, 0}; |
|
487 |
||
488 |
static uint FindShipTrack(Vehicle *v, uint tile, int dir, uint bits, uint skiptile, int *track) |
|
489 |
{ |
|
490 |
PathFindShip pfs; |
|
491 |
int i, best_track; |
|
492 |
uint best_bird_dist = 0; |
|
493 |
uint best_length = 0; |
|
494 |
uint r; |
|
495 |
byte ship_dir = v->direction & 3; |
|
496 |
||
497 |
pfs.dest_coords = v->dest_tile; |
|
498 |
pfs.skiptile = skiptile; |
|
499 |
||
500 |
best_track = -1; |
|
501 |
||
502 |
do { |
|
503 |
i = FIND_FIRST_BIT(bits); |
|
504 |
bits = KILL_FIRST_BIT(bits); |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
505 |
|
0 | 506 |
pfs.best_bird_dist = (uint)-1; |
507 |
pfs.best_length = (uint)-1; |
|
508 |
||
159
139cf78bfb28
(svn r160) -Codechange: made GetTileTrackStatus more readable (blathijs)
truelight
parents:
156
diff
changeset
|
509 |
FollowTrack(tile, 0x3800 | TRANSPORT_WATER, _ship_search_directions[i][dir], (TPFEnumProc*)ShipTrackFollower, NULL, &pfs); |
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
510 |
|
0 | 511 |
if (best_track >= 0) { |
512 |
if (pfs.best_bird_dist != 0) { |
|
513 |
/* neither reached the destination, pick the one with the smallest bird dist */ |
|
514 |
if (pfs.best_bird_dist > best_bird_dist) goto bad; |
|
515 |
if (pfs.best_bird_dist < best_bird_dist) goto good; |
|
516 |
} else { |
|
517 |
if (pfs.best_length > best_length) goto bad; |
|
518 |
if (pfs.best_length < best_length) goto good; |
|
519 |
} |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
520 |
|
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
521 |
/* if we reach this position, there's two paths of equal value so far. |
0 | 522 |
* pick one randomly. */ |
523 |
r = (byte)Random(); |
|
524 |
if (_pick_shiptrack_table[i] == ship_dir) r += 80; |
|
525 |
if (_pick_shiptrack_table[best_track] == ship_dir) r -= 80; |
|
526 |
if (r <= 127) goto bad; |
|
527 |
} |
|
528 |
good:; |
|
529 |
best_track = i; |
|
530 |
best_bird_dist = pfs.best_bird_dist; |
|
531 |
best_length = pfs.best_length; |
|
532 |
bad:; |
|
533 |
||
534 |
} while (bits != 0); |
|
535 |
||
536 |
*track = best_track; |
|
537 |
return best_bird_dist; |
|
538 |
} |
|
539 |
||
540 |
static int ChooseShipTrack(Vehicle *v, uint tile, int dir, uint tracks) |
|
541 |
{ |
|
542 |
uint b; |
|
543 |
uint tot_dist, dist; |
|
544 |
int track; |
|
545 |
uint tile2; |
|
546 |
||
547 |
assert(dir>=0 && dir<=3); |
|
548 |
tile2 = TILE_ADD(tile, -_tileoffs_by_dir[dir]); |
|
549 |
dir ^= 2; |
|
550 |
tot_dist = (uint)-1; |
|
551 |
b = GetTileShipTrackStatus(tile2) & _ship_sometracks[dir] & v->u.ship.state; |
|
552 |
if (b != 0) { |
|
553 |
dist = FindShipTrack(v, tile2, dir, b, tile, &track); |
|
554 |
if (dist != (uint)-1) |
|
555 |
tot_dist = dist + 1; |
|
556 |
} |
|
557 |
dist = FindShipTrack(v, tile, dir^2, tracks, 0, &track); |
|
558 |
if (dist > tot_dist) |
|
559 |
return -1; |
|
560 |
return track; |
|
561 |
} |
|
562 |
||
563 |
static const byte _new_vehicle_direction_table[11] = { |
|
564 |
0, 7, 6, 0, |
|
565 |
1, 0, 5, 0, |
|
566 |
2, 3, 4, |
|
567 |
}; |
|
568 |
||
569 |
static int ShipGetNewDirectionFromTiles(uint new_tile, uint old_tile) |
|
570 |
{ |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
571 |
uint offs = (GET_TILE_Y(new_tile) - GET_TILE_Y(old_tile) + 1) * 4 + |
0 | 572 |
GET_TILE_X(new_tile) - GET_TILE_X(old_tile) + 1; |
573 |
assert(offs < 11 && offs != 3 && offs != 7); |
|
574 |
return _new_vehicle_direction_table[offs]; |
|
575 |
} |
|
576 |
||
577 |
static int ShipGetNewDirection(Vehicle *v, int x, int y) |
|
578 |
{ |
|
579 |
uint offs = (y - v->y_pos + 1) * 4 + (x - v->x_pos + 1); |
|
580 |
assert(offs < 11 && offs != 3 && offs != 7); |
|
581 |
return _new_vehicle_direction_table[offs]; |
|
582 |
} |
|
583 |
||
584 |
static int GetAvailShipTracks(uint tile, int dir) |
|
585 |
{ |
|
159
139cf78bfb28
(svn r160) -Codechange: made GetTileTrackStatus more readable (blathijs)
truelight
parents:
156
diff
changeset
|
586 |
uint32 r = GetTileTrackStatus(tile, TRANSPORT_WATER); |
0 | 587 |
return (byte) ((r | r >> 8)) & _ship_sometracks[dir]; |
588 |
} |
|
589 |
||
590 |
static const byte _ship_subcoord[4][6][3] = { |
|
591 |
{ |
|
592 |
{15, 8, 1}, |
|
593 |
{ 0, 0, 0}, |
|
594 |
{ 0, 0, 0}, |
|
595 |
{15, 8, 2}, |
|
596 |
{15, 7, 0}, |
|
597 |
{ 0, 0, 0}, |
|
598 |
}, |
|
599 |
{ |
|
600 |
{ 0, 0, 0}, |
|
601 |
{ 8, 0, 3}, |
|
602 |
{ 7, 0, 2}, |
|
603 |
{ 0, 0, 0}, |
|
604 |
{ 8, 0, 4}, |
|
605 |
{ 0, 0, 0}, |
|
606 |
}, |
|
607 |
{ |
|
608 |
{ 0, 8, 5}, |
|
609 |
{ 0, 0, 0}, |
|
610 |
{ 0, 7, 6}, |
|
611 |
{ 0, 0, 0}, |
|
612 |
{ 0, 0, 0}, |
|
613 |
{ 0, 8, 4}, |
|
614 |
}, |
|
615 |
{ |
|
616 |
{ 0, 0, 0}, |
|
617 |
{ 8,15, 7}, |
|
618 |
{ 0, 0, 0}, |
|
619 |
{ 8,15, 6}, |
|
620 |
{ 0, 0, 0}, |
|
621 |
{ 7,15, 0}, |
|
622 |
} |
|
623 |
}; |
|
624 |
||
625 |
||
626 |
static void ShipController(Vehicle *v) |
|
627 |
{ |
|
628 |
GetNewVehiclePosResult gp; |
|
629 |
uint32 r; |
|
630 |
const byte *b; |
|
631 |
int dir,track,tracks; |
|
632 |
||
633 |
v->tick_counter++; |
|
634 |
||
635 |
if (v->breakdown_ctr != 0) { |
|
636 |
if (v->breakdown_ctr <= 2) { |
|
637 |
HandleBrokenShip(v); |
|
638 |
return; |
|
639 |
} |
|
640 |
v->breakdown_ctr--; |
|
641 |
} |
|
642 |
||
643 |
if (v->vehstatus & VS_STOPPED) |
|
644 |
return; |
|
645 |
||
646 |
ProcessShipOrder(v); |
|
647 |
HandleShipLoading(v); |
|
648 |
||
555
eec6c0294435
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
649 |
if (v->current_order.type == OT_LOADING) |
0 | 650 |
return; |
651 |
||
652 |
CheckShipLeaveDepot(v); |
|
653 |
||
654 |
if (!ShipAccelerate(v)) |
|
655 |
return; |
|
656 |
||
657 |
BeginVehicleMove(v); |
|
658 |
||
659 |
if (GetNewVehiclePos(v, &gp)) { |
|
660 |
// staying in tile |
|
661 |
if (v->u.ship.state == 0x80) { |
|
662 |
gp.x = v->x_pos; |
|
663 |
gp.y = v->y_pos; |
|
664 |
} else { |
|
665 |
/* isnot inside depot */ |
|
666 |
r = VehicleEnterTile(v, gp.new_tile, gp.x, gp.y); |
|
667 |
if (r & 0x8) goto reverse_direction; |
|
668 |
||
669 |
if (v->dest_tile != 0 && v->dest_tile == gp.new_tile) { |
|
555
eec6c0294435
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
670 |
if (v->current_order.type == OT_GOTO_DEPOT) { |
0 | 671 |
if ((gp.x&0xF)==8 && (gp.y&0xF)==8) { |
672 |
ShipEnterDepot(v); |
|
673 |
return; |
|
674 |
} |
|
555
eec6c0294435
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
675 |
} else if (v->current_order.type == OT_GOTO_STATION) { |
0 | 676 |
Station *st; |
677 |
||
555
eec6c0294435
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
678 |
v->last_station_visited = v->current_order.station; |
0 | 679 |
|
297
5a89d926db2d
(svn r303) Fix: [ 1022227 ] Ships could unload cargo at stations without docks
dominik
parents:
193
diff
changeset
|
680 |
/* Process station in the schedule. Don't do that for buoys (HVOT_BUOY) */ |
555
eec6c0294435
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
681 |
st = DEREF_STATION(v->current_order.station); |
297
5a89d926db2d
(svn r303) Fix: [ 1022227 ] Ships could unload cargo at stations without docks
dominik
parents:
193
diff
changeset
|
682 |
if (!(st->had_vehicle_of_type & HVOT_BUOY) |
5a89d926db2d
(svn r303) Fix: [ 1022227 ] Ships could unload cargo at stations without docks
dominik
parents:
193
diff
changeset
|
683 |
&& (st->facilities & FACIL_DOCK)) { /* ugly, ugly workaround for problem with ships able to drop off cargo at wrong stations */ |
555
eec6c0294435
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
684 |
v->current_order.type = OT_LOADING; |
eec6c0294435
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
685 |
v->current_order.flags &= OF_FULL_LOAD | OF_UNLOAD; |
eec6c0294435
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
686 |
v->current_order.flags |= OF_NON_STOP; |
0 | 687 |
ShipArrivesAt(v, st); |
688 |
||
689 |
SET_EXPENSES_TYPE(EXPENSES_SHIP_INC); |
|
690 |
if (LoadUnloadVehicle(v)) { |
|
691 |
InvalidateWindow(WC_SHIPS_LIST, v->owner); |
|
692 |
MarkShipDirty(v); |
|
693 |
} |
|
694 |
InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); |
|
297
5a89d926db2d
(svn r303) Fix: [ 1022227 ] Ships could unload cargo at stations without docks
dominik
parents:
193
diff
changeset
|
695 |
} else { /* leave buoys right aways */ |
555
eec6c0294435
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
696 |
v->current_order.type = OT_LEAVESTATION; |
eec6c0294435
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
697 |
v->current_order.flags = 0; |
0 | 698 |
v->cur_order_index++; |
699 |
InvalidateVehicleOrderWidget(v); |
|
700 |
} |
|
701 |
goto else_end; |
|
702 |
} |
|
703 |
} |
|
704 |
||
555
eec6c0294435
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
705 |
if (v->current_order.type == OT_LEAVESTATION) { |
eec6c0294435
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
706 |
v->current_order.type = OT_NOTHING; |
eec6c0294435
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
707 |
v->current_order.flags = 0; |
0 | 708 |
InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); |
709 |
} |
|
710 |
} |
|
711 |
} else { |
|
712 |
// new tile |
|
713 |
if (GET_TILE_X(gp.new_tile) == 0xFF || |
|
714 |
(byte)GET_TILE_Y(gp.new_tile) == 0xFF) |
|
715 |
goto reverse_direction; |
|
716 |
||
717 |
dir = ShipGetNewDirectionFromTiles(gp.new_tile, gp.old_tile); |
|
718 |
assert(dir == 1 || dir == 3 || dir == 5 || dir == 7); |
|
719 |
dir>>=1; |
|
720 |
tracks = GetAvailShipTracks(gp.new_tile, dir); |
|
721 |
if (tracks == 0) |
|
722 |
goto reverse_direction; |
|
723 |
||
724 |
// Choose a direction, and continue if we find one |
|
725 |
track = ChooseShipTrack(v, gp.new_tile, dir, tracks); |
|
726 |
if (track < 0) |
|
727 |
goto reverse_direction; |
|
728 |
||
729 |
b = _ship_subcoord[dir][track]; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
730 |
|
0 | 731 |
gp.x = (gp.x&~0xF) | b[0]; |
732 |
gp.y = (gp.y&~0xF) | b[1]; |
|
733 |
||
734 |
/* Call the landscape function and tell it that the vehicle entered the tile */ |
|
735 |
r = VehicleEnterTile(v, gp.new_tile, gp.x, gp.y); |
|
736 |
if (r&0x8) goto reverse_direction; |
|
737 |
||
738 |
if (!(r&0x4)) { |
|
739 |
v->tile = gp.new_tile; |
|
740 |
v->u.ship.state = 1 << track; |
|
741 |
} |
|
742 |
||
743 |
v->direction = b[2]; |
|
744 |
} |
|
745 |
else_end:; |
|
746 |
||
747 |
/* update image of ship, as well as delta XY */ |
|
748 |
dir = ShipGetNewDirection(v, gp.x, gp.y); |
|
749 |
v->x_pos = gp.x; |
|
750 |
v->y_pos = gp.y; |
|
751 |
v->z_pos = GetSlopeZ(gp.x, gp.y); |
|
752 |
||
753 |
getout: |
|
754 |
UpdateShipDeltaXY(v, dir); |
|
755 |
v->cur_image = GetShipImage(v, dir); |
|
756 |
VehiclePositionChanged(v); |
|
757 |
EndVehicleMove(v); |
|
758 |
return; |
|
759 |
||
760 |
reverse_direction: |
|
761 |
dir = v->direction ^ 4; |
|
762 |
v->direction = dir; |
|
763 |
goto getout; |
|
764 |
} |
|
765 |
||
766 |
static void AgeShipCargo(Vehicle *v) |
|
767 |
{ |
|
768 |
if (_age_cargo_skip_counter != 0) |
|
769 |
return; |
|
770 |
if (v->cargo_days != 255) |
|
771 |
v->cargo_days++; |
|
772 |
} |
|
773 |
||
774 |
void Ship_Tick(Vehicle *v) |
|
775 |
{ |
|
776 |
AgeShipCargo(v); |
|
777 |
ShipController(v); |
|
778 |
} |
|
779 |
||
780 |
void HandleClickOnShip(Vehicle *v) |
|
781 |
{ |
|
782 |
ShowShipViewWindow(v); |
|
783 |
} |
|
784 |
||
785 |
void ShipsYearlyLoop() |
|
786 |
{ |
|
787 |
Vehicle *v; |
|
788 |
||
789 |
FOR_ALL_VEHICLES(v) { |
|
790 |
if (v->type == VEH_Ship) { |
|
791 |
v->profit_last_year = v->profit_this_year; |
|
792 |
v->profit_this_year = 0; |
|
793 |
InvalidateWindow(WC_VEHICLE_DETAILS, v->index); |
|
794 |
} |
|
795 |
} |
|
796 |
} |
|
797 |
||
798 |
static int32 EstimateShipCost(uint16 engine_type) |
|
799 |
{ |
|
538
5dd99f3b7eca
(svn r920) Replace vehicle info macros with inline functions and add asserts to check limits
tron
parents:
534
diff
changeset
|
800 |
return ShipVehInfo(engine_type)->base_cost * (_price.ship_base>>3)>>5; |
0 | 801 |
} |
802 |
||
803 |
// p1 = type to build |
|
804 |
int32 CmdBuildShip(int x, int y, uint32 flags, uint32 p1, uint32 p2) |
|
805 |
{ |
|
806 |
int32 value; |
|
807 |
Vehicle *v; |
|
808 |
uint unit_num; |
|
809 |
uint tile = TILE_FROM_XY(x,y); |
|
810 |
Engine *e; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
811 |
|
0 | 812 |
SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES); |
813 |
||
814 |
value = EstimateShipCost(p1); |
|
815 |
if (flags & DC_QUERY_COST) |
|
816 |
return value; |
|
817 |
||
818 |
v = AllocateVehicle(); |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
819 |
if (v == NULL || _ptr_to_next_order >= endof(_order_array) || |
0 | 820 |
(unit_num = GetFreeUnitNumber(VEH_Ship)) > _patches.max_ships) |
821 |
return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME); |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
822 |
|
0 | 823 |
if (flags & DC_EXEC) { |
538
5dd99f3b7eca
(svn r920) Replace vehicle info macros with inline functions and add asserts to check limits
tron
parents:
534
diff
changeset
|
824 |
const ShipVehicleInfo *svi = ShipVehInfo(p1); |
5dd99f3b7eca
(svn r920) Replace vehicle info macros with inline functions and add asserts to check limits
tron
parents:
534
diff
changeset
|
825 |
|
0 | 826 |
v->unitnumber = unit_num; |
827 |
||
828 |
v->owner = _current_player; |
|
829 |
v->tile = tile; |
|
830 |
x = GET_TILE_X(tile)*16 + 8; |
|
831 |
y = GET_TILE_Y(tile)*16 + 8; |
|
832 |
v->x_pos = x; |
|
833 |
v->y_pos = y; |
|
834 |
v->z_pos = GetSlopeZ(x,y); |
|
835 |
||
836 |
v->z_height = 6; |
|
837 |
v->sprite_width = 6; |
|
838 |
v->sprite_height = 6; |
|
839 |
v->x_offs = -3; |
|
840 |
v->y_offs = -3; |
|
841 |
v->vehstatus = VS_HIDDEN | VS_STOPPED | VS_DEFPAL; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
842 |
|
538
5dd99f3b7eca
(svn r920) Replace vehicle info macros with inline functions and add asserts to check limits
tron
parents:
534
diff
changeset
|
843 |
v->spritenum = svi->image_index; |
5dd99f3b7eca
(svn r920) Replace vehicle info macros with inline functions and add asserts to check limits
tron
parents:
534
diff
changeset
|
844 |
v->cargo_type = svi->cargo_type; |
5dd99f3b7eca
(svn r920) Replace vehicle info macros with inline functions and add asserts to check limits
tron
parents:
534
diff
changeset
|
845 |
v->cargo_cap = svi->capacity; |
0 | 846 |
v->value = value; |
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
847 |
|
0 | 848 |
v->last_station_visited = 255; |
538
5dd99f3b7eca
(svn r920) Replace vehicle info macros with inline functions and add asserts to check limits
tron
parents:
534
diff
changeset
|
849 |
v->max_speed = svi->max_speed; |
0 | 850 |
v->engine_type = (byte)p1; |
851 |
||
852 |
e = &_engines[p1]; |
|
853 |
v->reliability = e->reliability; |
|
854 |
v->reliability_spd_dec = e->reliability_spd_dec; |
|
855 |
v->max_age = e->lifelength * 366; |
|
856 |
_new_ship_id = v->index; |
|
857 |
||
858 |
v->string_id = STR_SV_SHIP_NAME; |
|
859 |
v->u.ship.state = 0x80; |
|
555
eec6c0294435
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
860 |
_ptr_to_next_order->type = OT_NOTHING; |
eec6c0294435
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
861 |
_ptr_to_next_order->flags = 0; |
eec6c0294435
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
862 |
v->schedule_ptr = _ptr_to_next_order++; |
0 | 863 |
|
864 |
v->service_interval = _patches.servint_ships; |
|
865 |
v->date_of_last_service = _date; |
|
866 |
v->build_year = _cur_year; |
|
867 |
v->cur_image = 0x0E5E; |
|
868 |
v->type = VEH_Ship; |
|
869 |
||
870 |
VehiclePositionChanged(v); |
|
871 |
||
872 |
InvalidateWindow(WC_VEHICLE_DEPOT, v->tile); |
|
164
0cbdf3c9bde1
(svn r165) -Feature: Option to sort vehicles in vehicle-list window by different criteria. Total independent sort for all types and players. Periodic resort of list every 10 TTD days. Thank you for your graphical inspiration follow and buxo (since none of you provided any code).
darkvater
parents:
159
diff
changeset
|
873 |
_vehicle_sort_dirty[VEHSHIP] = true; // build a ship |
0 | 874 |
InvalidateWindow(WC_SHIPS_LIST, v->owner); |
875 |
InvalidateWindow(WC_COMPANY, v->owner); |
|
876 |
} |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
877 |
|
0 | 878 |
return value; |
879 |
} |
|
880 |
||
881 |
int32 CmdSellShip(int x, int y, uint32 flags, uint32 p1, uint32 p2) |
|
882 |
{ |
|
883 |
Vehicle *v; |
|
884 |
||
885 |
SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES); |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
886 |
|
0 | 887 |
v = &_vehicles[p1]; |
888 |
||
889 |
if (!CheckOwnership(v->owner)) |
|
890 |
return CMD_ERROR; |
|
891 |
||
892 |
if (!IsShipDepotTile(v->tile) || v->u.road.state != 0x80 || !(v->vehstatus&VS_STOPPED)) |
|
893 |
return_cmd_error(STR_980B_SHIP_MUST_BE_STOPPED_IN); |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
894 |
|
0 | 895 |
if (flags & DC_EXEC) { |
896 |
InvalidateWindow(WC_VEHICLE_DEPOT, v->tile); |
|
164
0cbdf3c9bde1
(svn r165) -Feature: Option to sort vehicles in vehicle-list window by different criteria. Total independent sort for all types and players. Periodic resort of list every 10 TTD days. Thank you for your graphical inspiration follow and buxo (since none of you provided any code).
darkvater
parents:
159
diff
changeset
|
897 |
_vehicle_sort_dirty[VEHSHIP] = true; // sell a ship |
0 | 898 |
InvalidateWindow(WC_SHIPS_LIST, v->owner); |
899 |
InvalidateWindow(WC_COMPANY, v->owner); |
|
900 |
DeleteWindowById(WC_VEHICLE_VIEW, v->index); |
|
901 |
DeleteVehicle(v); |
|
902 |
} |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
903 |
|
0 | 904 |
return -(int32)v->value; |
905 |
} |
|
906 |
||
907 |
// p1 = vehicle |
|
908 |
int32 CmdStartStopShip(int x, int y, uint32 flags, uint32 p1, uint32 p2) |
|
909 |
{ |
|
910 |
Vehicle *v; |
|
911 |
||
912 |
v = &_vehicles[p1]; |
|
913 |
||
914 |
if (!CheckOwnership(v->owner)) |
|
915 |
return CMD_ERROR; |
|
916 |
||
917 |
if (flags & DC_EXEC) { |
|
918 |
v->vehstatus ^= VS_STOPPED; |
|
919 |
InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); |
|
920 |
InvalidateWindow(WC_VEHICLE_DEPOT, v->tile); |
|
921 |
} |
|
922 |
||
923 |
return 0; |
|
924 |
} |
|
925 |
||
926 |
int32 CmdSendShipToDepot(int x, int y, uint32 flags, uint32 p1, uint32 p2) |
|
927 |
{ |
|
928 |
Vehicle *v; |
|
929 |
int depot; |
|
930 |
||
931 |
v = &_vehicles[p1]; |
|
932 |
||
933 |
if (!CheckOwnership(v->owner)) |
|
934 |
return CMD_ERROR; |
|
935 |
||
555
eec6c0294435
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
936 |
if (v->current_order.type == OT_GOTO_DEPOT) { |
0 | 937 |
if (flags & DC_EXEC) { |
555
eec6c0294435
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
938 |
if (v->current_order.flags & OF_UNLOAD) v->cur_order_index++; |
eec6c0294435
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
939 |
v->current_order.type = OT_DUMMY; |
eec6c0294435
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
940 |
v->current_order.flags = 0; |
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
941 |
InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); |
0 | 942 |
} |
943 |
} else { |
|
944 |
depot = FindClosestShipDepot(v); |
|
945 |
if (depot < 0) |
|
946 |
return_cmd_error(STR_981A_UNABLE_TO_FIND_LOCAL_DEPOT); |
|
947 |
||
948 |
if (flags & DC_EXEC) { |
|
949 |
v->dest_tile = _depots[depot].xy; |
|
555
eec6c0294435
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
950 |
v->current_order.type = OT_GOTO_DEPOT; |
eec6c0294435
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
951 |
v->current_order.flags = OF_NON_STOP | OF_FULL_LOAD; |
eec6c0294435
(svn r955) Replace uint16 for orders with struct Order
tron
parents:
541
diff
changeset
|
952 |
v->current_order.station = depot; |
0 | 953 |
InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, 4); |
954 |
} |
|
955 |
} |
|
956 |
||
957 |
return 0; |
|
958 |
} |
|
959 |
||
960 |
int32 CmdChangeShipServiceInt(int x, int y, uint32 flags, uint32 p1, uint32 p2) |
|
961 |
{ |
|
962 |
Vehicle *v; |
|
963 |
||
964 |
v = &_vehicles[p1]; |
|
965 |
||
966 |
if (!CheckOwnership(v->owner)) |
|
967 |
return CMD_ERROR; |
|
968 |
||
969 |
if (flags & DC_EXEC) { |
|
970 |
v->service_interval = (uint16)p2; |
|
971 |
InvalidateWindowWidget(WC_VEHICLE_DETAILS, v->index, 7); |
|
972 |
} |
|
973 |
||
974 |
return 0; |
|
975 |
} |
|
976 |
||
977 |
||
978 |
// p1 = vehicle |
|
979 |
// p2 = new cargo |
|
980 |
int32 CmdRefitShip(int x, int y, uint32 flags, uint32 p1, uint32 p2) |
|
981 |
{ |
|
982 |
Vehicle *v; |
|
983 |
int32 cost; |
|
984 |
||
985 |
SET_EXPENSES_TYPE(EXPENSES_SHIP_RUN); |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
164
diff
changeset
|
986 |
|
0 | 987 |
v = &_vehicles[p1]; |
988 |
if (!CheckOwnership(v->owner)) |
|
989 |
return CMD_ERROR; |
|
990 |
||
991 |
if (!IsShipDepotTile(v->tile) || |
|
992 |
!(v->vehstatus&VS_STOPPED) || |
|
993 |
v->u.ship.state != 0x80) |
|
994 |
return_cmd_error(STR_980B_SHIP_MUST_BE_STOPPED_IN); |
|
995 |
||
996 |
cost = 0; |
|
997 |
if (IS_HUMAN_PLAYER(v->owner) && (byte)p2 != v->cargo_type) { |
|
998 |
cost = _price.ship_base >> 7; |
|
999 |
} |
|
1000 |
||
1001 |
if (flags & DC_EXEC) { |
|
1002 |
v->cargo_count = 0; |
|
1003 |
v->cargo_type = (byte)p2; |
|
1004 |
InvalidateWindow(WC_VEHICLE_DETAILS, v->index); |
|
1005 |
} |
|
1006 |
||
1007 |
return cost; |
|
1008 |
||
1009 |
} |
|
1010 |
||
1011 |