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;
647 _new_vehicle_id = v->
index;
658 if (w->
tile == tile &&
686 static void AddRearEngineToMultiheadedTrain(
Train *v)
704 u->railtype = v->railtype;
715 v->other_multiheaded_part = u;
716 u->other_multiheaded_part = v;
750 v->
z_pos = GetSlopePixelZ(x, y);
767 v->railtype = rvi->railtype;
768 _new_vehicle_id = v->
index;
787 AddRearEngineToMultiheadedTrain(v);
805 static Train *FindGoodVehiclePos(
const Train *src)
811 FOR_ALL_TRAINS(dst) {
817 if (t == NULL)
return dst;
835 for (; t != NULL; t = t->
Next()) *list.
Append() = t;
845 if (list.
Length() == 0)
return;
849 for (
Train **iter = list.
Begin(); iter != list.
End(); iter++) {
906 if (u == t->other_multiheaded_part)
continue;
922 if (chain == NULL)
return;
956 if ((src != NULL && src->
IsEngine() ? 1 : 0) +
957 (dst != NULL && dst->
IsEngine() ? 1 : 0) -
958 (original_src != NULL && original_src->
IsEngine() ? 1 : 0) -
959 (original_dst != NULL && original_dst->
IsEngine() ? 1 : 0) <= 0) {
1026 if (head->
GetGRF()->grf_version < 8) {
1027 if (callback == 0xFD) error = STR_ERROR_INCOMPATIBLE_RAIL_TYPES;
1031 if (callback < 0x400) {
1041 error = STR_ERROR_INCOMPATIBLE_RAIL_TYPES;
1075 if (ret.
Failed())
return ret;
1077 if (ret.
Failed())
return ret;
1094 if (*src_head == *dst_head) {
1098 }
else if (*dst_head == NULL) {
1104 if (src == *src_head) {
1111 *src_head = move_chain ? NULL :
1135 if (head == NULL)
return;
1169 bool move_chain =
HasBit(p1, 20);
1175 if (ret.
Failed())
return ret;
1183 dst = src->
IsEngine() ? NULL : FindGoodVehiclePos(src);
1189 if (ret.
Failed())
return ret;
1208 dst_head = dst->
First();
1219 if (move_chain && src_head == dst_head)
return CommandCost();
1232 TrainList original_src;
1233 TrainList original_dst;
1241 Train *original_src_head = src_head;
1242 Train *original_dst_head = (dst_head == src_head ? NULL : dst_head);
1247 bool original_src_head_front_engine = original_src_head->
IsFrontEngine();
1248 bool original_dst_head_front_engine = original_dst_head != NULL && original_dst_head->
IsFrontEngine();
1315 if (original_src_head != src && dst_head == src) {
1362 bool sell_chain =
HasBit(data, 0);
1376 Train *sell_head = NULL;
1446 static const int _sign_table[] =
1459 this->
y_offs -= half_shorten * _sign_table[direction + 1];
1463 switch (direction) {
1528 uint16 flag1 = *swap_flag1;
1529 uint16 flag2 = *swap_flag2;
1596 for (a = v; l != 0; l--) a = a->
Next();
1597 for (b = v; r != 0; r--) b = b->
Next();
1607 Swap(a->track, b->track);
1696 if (new_state && sound) {
1730 uint length = CountVehiclesInChain(v);
1732 while (length > 2) {
1734 first = first->
Next();
1763 if (leave != NULL) {
1779 uint length = CountVehiclesInChain(v);
1783 bool nomove = (dep == NULL);
1785 while (length > 2) {
1788 if (base == dep)
break;
1791 if (last == dep) nomove =
true;
1794 first = first->
Next();
1799 for (
int i = 0; i < differential; i++)
TrainController(first, (nomove ? last->
Next() : NULL));
1823 int r = CountVehiclesInChain(v) - 1;
1841 ClrBit(v->flags, VRF_REVERSING);
1909 if (ret.
Failed())
return ret;
1915 return_cmd_error(STR_ERROR_CAN_T_REVERSE_DIRECTION_RAIL_VEHICLE_MULTIPLE_UNITS);
1942 while (last->
Next() != NULL) last = last->
Next();
1984 if (ret.
Failed())
return ret;
2020 default: NOT_REACHED();
2036 if (location != NULL) *location = tfdd.
tile;
2038 if (reverse != NULL) *reverse = tfdd.
reverse;
2046 static const SoundFx sfx[] = {
2057 SndPlayVehicleFx(sfx[RailVehInfo(engtype)->engclass],
this);
2078 case OT_GOTO_WAYPOINT:
2084 case OT_LEAVESTATION:
2129 for (
const Train *u = v; u != NULL; u = u->
Next()) {
2142 if (v->force_proceed ==
TFP_NONE) {
2262 for (
const Train *u = v; u != NULL; u = u->
Next()) {
2270 while (ft.
Follow(tile, td)) {
2305 static const byte _initial_tile_subcoord[6][4][3] = {
2306 {{ 15, 8, 1 }, { 0, 0, 0 }, { 0, 8, 5 }, { 0, 0, 0 }},
2307 {{ 0, 0, 0 }, { 8, 0, 3 }, { 0, 0, 0 }, { 8, 15, 7 }},
2308 {{ 0, 0, 0 }, { 7, 0, 2 }, { 0, 7, 6 }, { 0, 0, 0 }},
2309 {{ 15, 8, 2 }, { 0, 0, 0 }, { 0, 0, 0 }, { 8, 15, 6 }},
2310 {{ 15, 7, 0 }, { 8, 0, 4 }, { 0, 0, 0 }, { 0, 0, 0 }},
2311 {{ 0, 0, 0 }, { 0, 0, 0 }, { 0, 8, 4 }, { 7, 15, 0 }},
2332 default: NOT_REACHED();
2349 while (ft.
Follow(tile, cur_td)) {
2377 if (enterdir != NULL) *enterdir = ft.
m_exitdir;
2394 if (ft.m_err == CFollowTrackRail::EC_OWNER || ft.m_err == CFollowTrackRail::EC_NO_WAY) {
2404 while (tile != stopped || cur_td != stopped_td) {
2405 if (!ft.
Follow(tile, cur_td))
break;
2439 default: NOT_REACHED();
2449 StationID old_last_station_visited;
2451 bool suppress_implicit_orders;
2467 this->v->
dest_tile = this->old_dest_tile;
2481 if (skip_first) ++this->index;
2487 if (this->index >= this->v->
GetNumOrders()) this->index = 0;
2490 assert(order != NULL);
2496 case OT_GOTO_STATION:
2497 case OT_GOTO_WAYPOINT:
2500 case OT_CONDITIONAL: {
2528 bool changed_signal =
false;
2532 if (got_reservation != NULL) *got_reservation =
false;
2544 do_track_reservation =
true;
2545 changed_signal =
true;
2547 }
else if (!do_track_reservation) {
2555 if (do_track_reservation) {
2563 if (res_dest.okay) {
2565 if (got_reservation != NULL) *got_reservation =
true;
2588 orders.SwitchToNextOrder(
false);
2592 v->tile == v->dest_tile))) {
2593 orders.SwitchToNextOrder(
true);
2598 bool path_found =
true;
2601 Track next_track =
DoTrainPathfind(v, new_tile, dest_enterdir, tracks, path_found, do_track_reservation, &res_dest);
2602 if (new_tile == tile) best_track = next_track;
2607 if (!do_track_reservation)
return best_track;
2624 if (got_reservation != NULL) *got_reservation =
true;
2633 if (got_reservation != NULL) *got_reservation =
true;
2646 if (orders.SwitchToNextOrder(
true)) {
2649 DoTrainPathfind(v, next_tile, exitdir, reachable, path_found,
true, &cur_dest);
2651 res_dest = cur_dest;
2652 if (res_dest.okay)
continue;
2656 if (got_reservation != NULL) *got_reservation =
false;
2657 changed_signal =
false;
2665 if (got_reservation != NULL) *got_reservation =
false;
2666 changed_signal =
false;
2711 if (other_train != NULL && other_train->
index != v->
index) {
2716 if (origin.
okay && (v->
tile != origin.
tile || first_tile_okay)) {
2735 bool res_made =
false;
2736 ChooseTrainTrack(v, new_tile, exitdir, reachable,
true, &res_made, mark_as_stuck);
2753 static bool CheckReverseTrain(
const Train *v)
2767 default: NOT_REACHED();
2797 }
while ((v = v->
Next()) != NULL);
2814 default: NOT_REACHED();
2834 if (!(st->had_vehicle_of_type &
HVOT_TRAIN)) {
2838 STR_NEWS_FIRST_TRAIN_ARRIVAL,
2857 static inline bool CheckCompatibleRail(
const Train *v,
TileIndex tile)
2874 {256 / 4, 256 / 2, 256 / 4, 2},
2875 {256 / 4, 256 / 2, 256 / 4, 2},
2876 {0, 256 / 2, 256 / 4, 2},
2890 if (old_z < v->z_pos) {
2894 if (spd <= v->gcache.cached_max_track_speed) v->
cur_speed = spd;
2906 if (!IsPbsSignal(GetSignalType(tile,
TrackdirToTrack(trackdir))))
return true;
2915 for (
const Train *u =
this; u != NULL; u = u->
Next()) {
2944 for (
const Train *v =
this; v != NULL; v = v->
Next()) {
3018 if (coll == tcc->
v)
return NULL;
3027 uint hash = (y_diff + 7) | (x_diff + 7);
3028 if (hash & ~15)
return NULL;
3032 if (x_diff * x_diff + y_diff * y_diff > min_diff * min_diff)
return NULL;
3071 if (tcc.
num == 0)
return false;
3076 ModifyStationRatingAround(v->
tile, v->
owner, -160, 30);
3107 bool direction_changed =
false;
3110 for (prev = v->
Previous(); v != nomove; prev = v, v = v->
Next()) {
3112 bool update_signals_crossing =
false;
3164 if (!CheckCompatibleRail(v, gp.
new_tile))
goto invalid_rail;
3190 if ((red_signals & chosen_track) && v->force_proceed ==
TFP_NONE) {
3200 v->progress = 255 - 100;
3205 v->progress = 255 - 10;
3213 if (!
HasVehicleOnPos(o_tile, &exitdir, &CheckTrainAtSignal))
return false;
3223 v->wait_counter = 0;
3226 goto reverse_train_direction;
3238 chosen_track = bits;
3240 chosen_track = prev->track;
3258 chosen_track = _connecting_track[enterdir][exitdir];
3260 chosen_track &= bits;
3270 const byte *b = _initial_tile_subcoord[
FIND_FIRST_BIT(chosen_track)][enterdir];
3271 gp.x = (gp.x & ~0xF) | b[0];
3272 gp.
y = (gp.
y & ~0xF) | b[1];
3298 v->track = chosen_track;
3304 update_signals_crossing =
true;
3306 if (chosen_dir != v->direction) {
3312 direction_changed =
true;
3313 v->direction = chosen_dir;
3316 if (v->IsFrontEngine()) {
3317 v->wait_counter = 0;
3335 if (v->IsFrontEngine()) {
3347 v->UpdatePosition();
3348 if ((v->vehstatus &
VS_HIDDEN) == 0) v->Vehicle::UpdateViewport(
true);
3354 v->UpdateDeltaXY(v->direction);
3358 v->UpdatePosition();
3368 if (update_signals_crossing) {
3369 if (v->IsFrontEngine()) {
3370 if (TrainMovedChangeSignals(gp.
new_tile, enterdir)) {
3389 if (v->Next() == NULL) {
3405 if (prev != NULL)
error(
"Disconnecting train");
3407 reverse_train_direction:
3409 v->wait_counter = 0;
3434 *trackbits |= train_tbits;
3456 for (; v->
Next() != NULL; v = v->
Next()) u = v;
3514 static const DirDiff delta[] = {
3532 }
while ((v = v->
Next()) != NULL);
3549 if (state <= 200 &&
Chance16R(1, 7, r)) {
3550 int index = (r * 10 >> 16);
3564 }
while ((u = u->
Next()) != NULL);
3570 bool ret = v->
Next() != NULL;
3580 225, 210, 195, 180, 165, 150, 135, 120, 105, 90, 75, 60, 45, 30, 15, 15
3595 uint x = v->
x_pos & 0xF;
3596 uint y = v->
y_pos & 0xF;
3601 case DIR_N : x = ~x + ~y + 25;
break;
3603 case DIR_NE: x = ~x + 16;
break;
3604 case DIR_E : x = ~x + y + 9;
break;
3605 case DIR_SE: x = y;
break;
3606 case DIR_S : x = x + y - 7;
break;
3607 case DIR_W : x = ~y + x + 9;
break;
3625 uint16 break_speed = _breakdown_speeds[x & 0xF];
3626 if (break_speed < v->cur_speed) v->
cur_speed = break_speed;
3679 !CheckCompatibleRail(v, tile)) {
3702 uint16 break_speed = _breakdown_speeds[
GB(~t, 4, 4)];
3703 if (break_speed < v->cur_speed) v->
cur_speed = break_speed;
3745 static bool TrainLocoHandler(
Train *v,
bool mode)
3752 if (v->force_proceed !=
TFP_NONE) {
3822 if (v->force_proceed ==
TFP_NONE)
return true;
3860 if (j < adv_spd || v->cur_speed == 0)
break;
3864 if ((order_type == OT_GOTO_WAYPOINT || order_type == OT_GOTO_STATION) &&
3874 for (
Train *u = v; u != NULL; u = u->
Next()) {
3892 const Train *v =
this;
3896 if (e->u.rail.running_cost_class == INVALID_PRICE)
continue;
3899 if (cost_factor == 0)
continue;
3904 cost +=
GetPrice(e->u.rail.running_cost_class, cost_factor, e->
GetGRF());
3923 if (!TrainLocoHandler(
this,
false))
return false;
3925 return TrainLocoHandler(
this,
true);
3953 default: NOT_REACHED();
3991 CheckVehicleBreakdown(
this);