39 #include "table/strings.h"
51 static const byte _vehicle_initial_x_fract[4] = {10, 8, 4, 8};
52 static const byte _vehicle_initial_y_fract[4] = { 8, 4, 8, 10};
55 bool IsValidImageIndex<VEH_TRAIN>(uint8 image_index)
57 return image_index <
lengthof(_engine_sprite_base);
74 if (!
HasBit(direction, 0) && track != state_dir_table[diagdir]) {
101 for (
const Train *u = v, *w = v->
Next(); w != NULL; u = w, w = w->
Next()) {
104 max(
abs(u->x_pos - w->x_pos),
abs(u->y_pos - w->y_pos)) != u->CalcNextVehicleOffset()) ||
131 uint16 max_speed = UINT16_MAX;
140 bool train_can_tilt =
true;
142 for (
Train *u =
this; u != NULL; u = u->
Next()) {
146 assert(u->First() ==
this);
149 u->gcache.first_engine =
this == u ?
INVALID_ENGINE : first_engine;
150 u->railtype = rvi_u->railtype;
152 if (u->IsEngine()) first_engine = u->engine_type;
156 this->InvalidateNewGRFCache();
157 u->InvalidateNewGRFCache();
160 for (
Train *u =
this; u != NULL; u = u->
Next()) {
164 u->InvalidateNewGRFCache();
167 for (
Train *u =
this; u != NULL; u = u->
Next()) {
168 const Engine *e_u = u->GetEngine();
174 u->tcache.cached_override = GetWagonOverrideSpriteSet(u->engine_type, u->cargo_type, u->gcache.first_engine);
177 u->colourmap = PAL_NONE;
180 u->UpdateVisualEffect(
true);
190 if (!u->IsArticulatedPart()) {
193 if (rvi_u->
power > 0) {
207 if (speed != 0) max_speed =
min(speed, max_speed);
214 if (u->cargo_cap > new_cap) u->cargo.Truncate(new_cap);
215 u->refit_cap =
min(new_cap, u->refit_cap);
216 u->cargo_cap = new_cap;
225 if (e_u->
GetGRF() != NULL && e_u->
GetGRF()->grf_version >= 8) {
241 u->gcache.cached_veh_length = veh_len;
249 u->InvalidateNewGRFCache();
298 default: NOT_REACHED();
309 stop = *station_length;
325 assert(this->
First() ==
this);
327 static const int absolute_max_speed = UINT16_MAX;
328 int max_speed = absolute_max_speed;
332 int curvecount[2] = {0, 0};
339 for (
const Vehicle *u =
this; u->
Next() != NULL; u = u->
Next(), pos++) {
341 Direction next_dir = u->Next()->direction;
351 sum += pos - lastpos;
352 if (pos - lastpos == 1 && max_speed > 88) {
365 if (numcurve > 0 && max_speed > 88) {
366 if (curvecount[0] == 1 && curvecount[1] == 1) {
367 max_speed = absolute_max_speed;
370 max_speed = 232 - (13 -
Clamp(sum, 1, 12)) * (13 -
Clamp(sum, 1, 12));
374 if (max_speed != absolute_max_speed) {
381 max_speed += max_speed / 5;
407 int distance_to_go = station_ahead /
TILE_SIZE - (station_length - stop_at) /
TILE_SIZE;
409 if (distance_to_go > 0) {
410 int st_max_speed = 120;
412 int delta_v = this->
cur_speed / (distance_to_go + 1);
413 if (max_speed > (this->
cur_speed - delta_v)) {
414 st_max_speed = this->
cur_speed - (delta_v / 10);
417 st_max_speed =
max(st_max_speed, 25 * distance_to_go);
418 max_speed =
min(max_speed, st_max_speed);
423 for (
const Train *u =
this; u != NULL; u = u->
Next()) {
425 max_speed =
min(max_speed, 61);
457 int reference_width = TRAININFO_DEFAULT_VEHICLE_WIDTH;
458 int vehicle_pitch = 0;
461 if (e->
GetGRF() != NULL && is_custom_sprite(e->u.rail.image_index)) {
466 if (offset != NULL) {
475 assert(IsValidImageIndex<VEH_TRAIN>(spritenum));
476 return ((direction + _engine_sprite_add[spritenum]) & _engine_sprite_and[spritenum]) + _engine_sprite_base[
spritenum];
492 if (is_custom_sprite(spritenum)) {
493 sprite = GetCustomVehicleSprite(
this, (
Direction)(direction + 4 * IS_CUSTOM_SECONDHEAD_SPRITE(spritenum)), image_type);
494 if (sprite != 0)
return sprite;
499 assert(IsValidImageIndex<VEH_TRAIN>(spritenum));
500 sprite = GetDefaultTrainSprite(spritenum, direction);
511 uint8 spritenum = e->u.rail.image_index;
513 if (is_custom_sprite(spritenum)) {
514 SpriteID sprite = GetCustomVehicleIcon(engine, dir, image_type);
516 if (e->
GetGRF() != NULL) {
522 spritenum =
Engine::Get(engine)->original_image_index;
525 if (rear_head) spritenum++;
527 return GetDefaultTrainSprite(spritenum,
DIR_W);
536 SpriteID spritef = GetRailIcon(engine,
false, yf, image_type);
537 SpriteID spriter = GetRailIcon(engine,
true, yr, image_type);
541 preferred_x =
Clamp(preferred_x,
548 SpriteID sprite = GetRailIcon(engine,
false, y, image_type);
550 preferred_x =
Clamp(preferred_x,
570 SpriteID sprite = GetRailIcon(engine,
false, y, image_type);
579 sprite = GetRailIcon(engine,
true, y, image_type);
580 real_sprite = GetSprite(sprite,
ST_NORMAL);
585 xoffs = xoffs -
ScaleGUITrad(TRAININFO_DEFAULT_VEHICLE_WIDTH) / 2;
623 v->
z_pos = GetSlopePixelZ(x, y);
637 v->railtype = rvi->railtype;
648 _new_vehicle_id = v->
index;
659 if (w->
tile == tile &&
687 static void AddRearEngineToMultiheadedTrain(
Train *v)
705 u->railtype = v->railtype;
717 v->other_multiheaded_part = u;
718 u->other_multiheaded_part = v;
752 v->
z_pos = GetSlopePixelZ(x, y);
769 v->railtype = rvi->railtype;
770 _new_vehicle_id = v->
index;
789 AddRearEngineToMultiheadedTrain(v);
807 static Train *FindGoodVehiclePos(
const Train *src)
813 FOR_ALL_TRAINS(dst) {
819 if (t == NULL)
return dst;
837 for (; t != NULL; t = t->
Next()) *list.
Append() = t;
847 if (list.
Length() == 0)
return;
851 for (
Train **iter = list.
Begin(); iter != list.
End(); iter++) {
908 if (u == t->other_multiheaded_part)
continue;
924 if (chain == NULL)
return;
958 if ((src != NULL && src->
IsEngine() ? 1 : 0) +
959 (dst != NULL && dst->
IsEngine() ? 1 : 0) -
960 (original_src != NULL && original_src->
IsEngine() ? 1 : 0) -
961 (original_dst != NULL && original_dst->
IsEngine() ? 1 : 0) <= 0) {
1028 if (head->
GetGRF()->grf_version < 8) {
1029 if (callback == 0xFD) error = STR_ERROR_INCOMPATIBLE_RAIL_TYPES;
1033 if (callback < 0x400) {
1043 error = STR_ERROR_INCOMPATIBLE_RAIL_TYPES;
1077 if (ret.
Failed())
return ret;
1079 if (ret.
Failed())
return ret;
1096 if (*src_head == *dst_head) {
1100 }
else if (*dst_head == NULL) {
1106 if (src == *src_head) {
1113 *src_head = move_chain ? NULL :
1137 if (head == NULL)
return;
1171 bool move_chain =
HasBit(p1, 20);
1177 if (ret.
Failed())
return ret;
1185 dst = src->
IsEngine() ? NULL : FindGoodVehiclePos(src);
1191 if (ret.
Failed())
return ret;
1210 dst_head = dst->
First();
1221 if (move_chain && src_head == dst_head)
return CommandCost();
1234 TrainList original_src;
1235 TrainList original_dst;
1243 Train *original_src_head = src_head;
1244 Train *original_dst_head = (dst_head == src_head ? NULL : dst_head);
1249 bool original_src_head_front_engine = original_src_head->
IsFrontEngine();
1250 bool original_dst_head_front_engine = original_dst_head != NULL && original_dst_head->
IsFrontEngine();
1317 if (original_src_head != src && dst_head == src) {
1364 bool sell_chain =
HasBit(data, 0);
1378 Train *sell_head = NULL;
1448 static const int _sign_table[] =
1461 this->
y_offs -= half_shorten * _sign_table[direction + 1];
1465 switch (direction) {
1530 uint16 flag1 = *swap_flag1;
1531 uint16 flag2 = *swap_flag2;
1598 for (a = v; l != 0; l--) a = a->
Next();
1599 for (b = v; r != 0; r--) b = b->
Next();
1609 Swap(a->track, b->track);
1698 if (new_state && sound) {
1732 uint length = CountVehiclesInChain(v);
1734 while (length > 2) {
1736 first = first->
Next();
1765 if (leave != NULL) {
1781 uint length = CountVehiclesInChain(v);
1785 bool nomove = (dep == NULL);
1787 while (length > 2) {
1790 if (base == dep)
break;
1793 if (last == dep) nomove =
true;
1796 first = first->
Next();
1801 for (
int i = 0; i < differential; i++)
TrainController(first, (nomove ? last->
Next() : NULL));
1825 int r = CountVehiclesInChain(v) - 1;
1843 ClrBit(v->flags, VRF_REVERSING);
1911 if (ret.
Failed())
return ret;
1917 return_cmd_error(STR_ERROR_CAN_T_REVERSE_DIRECTION_RAIL_VEHICLE_MULTIPLE_UNITS);
1944 while (last->
Next() != NULL) last = last->
Next();
1986 if (ret.
Failed())
return ret;
2022 default: NOT_REACHED();
2038 if (location != NULL) *location = tfdd.
tile;
2040 if (reverse != NULL) *reverse = tfdd.
reverse;
2048 static const SoundFx sfx[] = {
2059 SndPlayVehicleFx(sfx[RailVehInfo(engtype)->engclass],
this);
2080 case OT_GOTO_WAYPOINT:
2086 case OT_LEAVESTATION:
2131 for (
const Train *u = v; u != NULL; u = u->
Next()) {
2144 if (v->force_proceed ==
TFP_NONE) {
2264 for (
const Train *u = v; u != NULL; u = u->
Next()) {
2272 while (ft.
Follow(tile, td)) {
2307 static const byte _initial_tile_subcoord[6][4][3] = {
2308 {{ 15, 8, 1 }, { 0, 0, 0 }, { 0, 8, 5 }, { 0, 0, 0 }},
2309 {{ 0, 0, 0 }, { 8, 0, 3 }, { 0, 0, 0 }, { 8, 15, 7 }},
2310 {{ 0, 0, 0 }, { 7, 0, 2 }, { 0, 7, 6 }, { 0, 0, 0 }},
2311 {{ 15, 8, 2 }, { 0, 0, 0 }, { 0, 0, 0 }, { 8, 15, 6 }},
2312 {{ 15, 7, 0 }, { 8, 0, 4 }, { 0, 0, 0 }, { 0, 0, 0 }},
2313 {{ 0, 0, 0 }, { 0, 0, 0 }, { 0, 8, 4 }, { 7, 15, 0 }},
2334 default: NOT_REACHED();
2351 while (ft.
Follow(tile, cur_td)) {
2379 if (enterdir != NULL) *enterdir = ft.
m_exitdir;
2396 if (ft.m_err == CFollowTrackRail::EC_OWNER || ft.m_err == CFollowTrackRail::EC_NO_WAY) {
2406 while (tile != stopped || cur_td != stopped_td) {
2407 if (!ft.
Follow(tile, cur_td))
break;
2441 default: NOT_REACHED();
2451 StationID old_last_station_visited;
2453 bool suppress_implicit_orders;
2469 this->v->
dest_tile = this->old_dest_tile;
2483 if (skip_first) ++this->index;
2489 if (this->index >= this->v->
GetNumOrders()) this->index = 0;
2492 assert(order != NULL);
2498 case OT_GOTO_STATION:
2499 case OT_GOTO_WAYPOINT:
2502 case OT_CONDITIONAL: {
2530 bool changed_signal =
false;
2534 if (got_reservation != NULL) *got_reservation =
false;
2546 do_track_reservation =
true;
2547 changed_signal =
true;
2549 }
else if (!do_track_reservation) {
2557 if (do_track_reservation) {
2565 if (res_dest.okay) {
2567 if (got_reservation != NULL) *got_reservation =
true;
2590 orders.SwitchToNextOrder(
false);
2594 v->tile == v->dest_tile))) {
2595 orders.SwitchToNextOrder(
true);
2600 bool path_found =
true;
2603 Track next_track =
DoTrainPathfind(v, new_tile, dest_enterdir, tracks, path_found, do_track_reservation, &res_dest);
2604 if (new_tile == tile) best_track = next_track;
2609 if (!do_track_reservation)
return best_track;
2626 if (got_reservation != NULL) *got_reservation =
true;
2635 if (got_reservation != NULL) *got_reservation =
true;
2648 if (orders.SwitchToNextOrder(
true)) {
2651 DoTrainPathfind(v, next_tile, exitdir, reachable, path_found,
true, &cur_dest);
2653 res_dest = cur_dest;
2654 if (res_dest.okay)
continue;
2658 if (got_reservation != NULL) *got_reservation =
false;
2659 changed_signal =
false;
2667 if (got_reservation != NULL) *got_reservation =
false;
2668 changed_signal =
false;
2713 if (other_train != NULL && other_train->
index != v->
index) {
2718 if (origin.
okay && (v->
tile != origin.
tile || first_tile_okay)) {
2737 bool res_made =
false;
2738 ChooseTrainTrack(v, new_tile, exitdir, reachable,
true, &res_made, mark_as_stuck);
2755 static bool CheckReverseTrain(
const Train *v)
2769 default: NOT_REACHED();
2799 }
while ((v = v->
Next()) != NULL);
2816 default: NOT_REACHED();
2836 if (!(st->had_vehicle_of_type &
HVOT_TRAIN)) {
2840 STR_NEWS_FIRST_TRAIN_ARRIVAL,
2859 static inline bool CheckCompatibleRail(
const Train *v,
TileIndex tile)
2876 {256 / 4, 256 / 2, 256 / 4, 2},
2877 {256 / 4, 256 / 2, 256 / 4, 2},
2878 {0, 256 / 2, 256 / 4, 2},
2892 if (old_z < v->z_pos) {
2896 if (spd <= v->gcache.cached_max_track_speed) v->
cur_speed = spd;
2908 if (!IsPbsSignal(GetSignalType(tile,
TrackdirToTrack(trackdir))))
return true;
2917 for (
const Train *u =
this; u != NULL; u = u->
Next()) {
2946 for (
const Train *v =
this; v != NULL; v = v->
Next()) {
3020 if (coll == tcc->
v)
return NULL;
3029 uint hash = (y_diff + 7) | (x_diff + 7);
3030 if (hash & ~15)
return NULL;
3034 if (x_diff * x_diff + y_diff * y_diff > min_diff * min_diff)
return NULL;
3073 if (tcc.
num == 0)
return false;
3078 ModifyStationRatingAround(v->
tile, v->
owner, -160, 30);
3109 bool direction_changed =
false;
3112 for (prev = v->
Previous(); v != nomove; prev = v, v = v->
Next()) {
3114 bool update_signals_crossing =
false;
3166 if (!CheckCompatibleRail(v, gp.
new_tile))
goto invalid_rail;
3192 if ((red_signals & chosen_track) && v->force_proceed ==
TFP_NONE) {
3202 v->progress = 255 - 100;
3207 v->progress = 255 - 10;
3215 if (!
HasVehicleOnPos(o_tile, &exitdir, &CheckTrainAtSignal))
return false;
3225 v->wait_counter = 0;
3228 goto reverse_train_direction;
3240 chosen_track = bits;
3242 chosen_track = prev->track;
3260 chosen_track = _connecting_track[enterdir][exitdir];
3262 chosen_track &= bits;
3272 const byte *b = _initial_tile_subcoord[
FIND_FIRST_BIT(chosen_track)][enterdir];
3273 gp.x = (gp.x & ~0xF) | b[0];
3274 gp.
y = (gp.
y & ~0xF) | b[1];
3300 v->track = chosen_track;
3306 update_signals_crossing =
true;
3308 if (chosen_dir != v->direction) {
3314 direction_changed =
true;
3315 v->direction = chosen_dir;
3318 if (v->IsFrontEngine()) {
3319 v->wait_counter = 0;
3337 if (v->IsFrontEngine()) {
3349 v->UpdatePosition();
3350 if ((v->vehstatus &
VS_HIDDEN) == 0) v->Vehicle::UpdateViewport(
true);
3356 v->UpdateDeltaXY(v->direction);
3360 v->UpdatePosition();
3370 if (update_signals_crossing) {
3371 if (v->IsFrontEngine()) {
3372 if (TrainMovedChangeSignals(gp.
new_tile, enterdir)) {
3391 if (v->Next() == NULL) {
3407 if (prev != NULL)
error(
"Disconnecting train");
3409 reverse_train_direction:
3411 v->wait_counter = 0;
3436 *trackbits |= train_tbits;
3458 for (; v->
Next() != NULL; v = v->
Next()) u = v;
3516 static const DirDiff delta[] = {
3534 }
while ((v = v->
Next()) != NULL);
3551 if (state <= 200 &&
Chance16R(1, 7, r)) {
3552 int index = (r * 10 >> 16);
3566 }
while ((u = u->
Next()) != NULL);
3572 bool ret = v->
Next() != NULL;
3582 225, 210, 195, 180, 165, 150, 135, 120, 105, 90, 75, 60, 45, 30, 15, 15
3597 uint x = v->
x_pos & 0xF;
3598 uint y = v->
y_pos & 0xF;
3603 case DIR_N : x = ~x + ~y + 25;
break;
3605 case DIR_NE: x = ~x + 16;
break;
3606 case DIR_E : x = ~x + y + 9;
break;
3607 case DIR_SE: x = y;
break;
3608 case DIR_S : x = x + y - 7;
break;
3609 case DIR_W : x = ~y + x + 9;
break;
3627 uint16 break_speed = _breakdown_speeds[x & 0xF];
3628 if (break_speed < v->cur_speed) v->
cur_speed = break_speed;
3681 !CheckCompatibleRail(v, tile)) {
3704 uint16 break_speed = _breakdown_speeds[
GB(~t, 4, 4)];
3705 if (break_speed < v->cur_speed) v->
cur_speed = break_speed;
3747 static bool TrainLocoHandler(
Train *v,
bool mode)
3754 if (v->force_proceed !=
TFP_NONE) {
3824 if (v->force_proceed ==
TFP_NONE)
return true;
3862 if (j < adv_spd || v->cur_speed == 0)
break;
3866 if ((order_type == OT_GOTO_WAYPOINT || order_type == OT_GOTO_STATION) &&
3876 for (
Train *u = v; u != NULL; u = u->
Next()) {
3894 const Train *v =
this;
3898 if (e->u.rail.running_cost_class == INVALID_PRICE)
continue;
3901 if (cost_factor == 0)
continue;
3906 cost +=
GetPrice(e->u.rail.running_cost_class, cost_factor, e->
GetGRF());
3925 if (!TrainLocoHandler(
this,
false))
return false;
3927 return TrainLocoHandler(
this,
true);
3955 default: NOT_REACHED();
3993 CheckVehicleBreakdown(
this);