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];
491 if (is_custom_sprite(spritenum)) {
492 GetCustomVehicleSprite(
this, (
Direction)(direction + 4 * IS_CUSTOM_SECONDHEAD_SPRITE(spritenum)), image_type, result);
498 assert(IsValidImageIndex<VEH_TRAIN>(spritenum));
499 SpriteID sprite = GetDefaultTrainSprite(spritenum, direction);
510 uint8 spritenum = e->u.rail.image_index;
512 if (is_custom_sprite(spritenum)) {
513 GetCustomVehicleIcon(engine, dir, image_type, result);
515 if (e->
GetGRF() != NULL) {
521 spritenum =
Engine::Get(engine)->original_image_index;
524 if (rear_head) spritenum++;
526 result->
Set(GetDefaultTrainSprite(spritenum,
DIR_W));
536 GetRailIcon(engine,
false, yf, image_type, &seqf);
537 GetRailIcon(engine,
true, yr, image_type, &seqr);
543 preferred_x =
Clamp(preferred_x,
551 GetRailIcon(engine,
false, y, image_type, &seq);
555 preferred_x =
Clamp(preferred_x,
577 GetRailIcon(engine,
false, y, image_type, &seq);
582 width =
UnScaleGUI(rect.right - rect.left + 1);
583 height =
UnScaleGUI(rect.bottom - rect.top + 1);
588 GetRailIcon(engine,
true, y, image_type, &seq);
593 height = max<uint>(height,
UnScaleGUI(rect.bottom - rect.top + 1));
594 xoffs = xoffs -
ScaleGUITrad(TRAININFO_DEFAULT_VEHICLE_WIDTH) / 2;
632 v->
z_pos = GetSlopePixelZ(x, y);
646 v->railtype = rvi->railtype;
657 _new_vehicle_id = v->
index;
668 if (w->
tile == tile &&
696 static void AddRearEngineToMultiheadedTrain(
Train *v)
714 u->railtype = v->railtype;
726 v->other_multiheaded_part = u;
727 u->other_multiheaded_part = v;
761 v->
z_pos = GetSlopePixelZ(x, y);
778 v->railtype = rvi->railtype;
779 _new_vehicle_id = v->
index;
798 AddRearEngineToMultiheadedTrain(v);
816 static Train *FindGoodVehiclePos(
const Train *src)
822 FOR_ALL_TRAINS(dst) {
828 if (t == NULL)
return dst;
846 for (; t != NULL; t = t->
Next()) *list.
Append() = t;
856 if (list.
Length() == 0)
return;
860 for (
Train **iter = list.
Begin(); iter != list.
End(); iter++) {
917 if (u == t->other_multiheaded_part)
continue;
933 if (chain == NULL)
return;
967 if ((src != NULL && src->
IsEngine() ? 1 : 0) +
968 (dst != NULL && dst->
IsEngine() ? 1 : 0) -
969 (original_src != NULL && original_src->
IsEngine() ? 1 : 0) -
970 (original_dst != NULL && original_dst->
IsEngine() ? 1 : 0) <= 0) {
1037 if (head->
GetGRF()->grf_version < 8) {
1038 if (callback == 0xFD) error = STR_ERROR_INCOMPATIBLE_RAIL_TYPES;
1042 if (callback < 0x400) {
1052 error = STR_ERROR_INCOMPATIBLE_RAIL_TYPES;
1086 if (ret.
Failed())
return ret;
1088 if (ret.
Failed())
return ret;
1105 if (*src_head == *dst_head) {
1109 }
else if (*dst_head == NULL) {
1115 if (src == *src_head) {
1122 *src_head = move_chain ? NULL :
1146 if (head == NULL)
return;
1180 bool move_chain =
HasBit(p1, 20);
1186 if (ret.
Failed())
return ret;
1194 dst = src->
IsEngine() ? NULL : FindGoodVehiclePos(src);
1200 if (ret.
Failed())
return ret;
1219 dst_head = dst->
First();
1230 if (move_chain && src_head == dst_head)
return CommandCost();
1243 TrainList original_src;
1244 TrainList original_dst;
1252 Train *original_src_head = src_head;
1253 Train *original_dst_head = (dst_head == src_head ? NULL : dst_head);
1258 bool original_src_head_front_engine = original_src_head->
IsFrontEngine();
1259 bool original_dst_head_front_engine = original_dst_head != NULL && original_dst_head->
IsFrontEngine();
1326 if (original_src_head != src && dst_head == src) {
1373 bool sell_chain =
HasBit(data, 0);
1387 Train *sell_head = NULL;
1457 static const int _sign_table[] =
1470 this->
y_offs -= half_shorten * _sign_table[direction + 1];
1474 switch (direction) {
1539 uint16 flag1 = *swap_flag1;
1540 uint16 flag2 = *swap_flag2;
1607 for (a = v; l != 0; l--) a = a->
Next();
1608 for (b = v; r != 0; r--) b = b->
Next();
1618 Swap(a->track, b->track);
1707 if (new_state && sound) {
1741 uint length = CountVehiclesInChain(v);
1743 while (length > 2) {
1745 first = first->
Next();
1774 if (leave != NULL) {
1790 uint length = CountVehiclesInChain(v);
1794 bool nomove = (dep == NULL);
1796 while (length > 2) {
1799 if (base == dep)
break;
1802 if (last == dep) nomove =
true;
1805 first = first->
Next();
1810 for (
int i = 0; i < differential; i++)
TrainController(first, (nomove ? last->
Next() : NULL));
1834 int r = CountVehiclesInChain(v) - 1;
1852 ClrBit(v->flags, VRF_REVERSING);
1920 if (ret.
Failed())
return ret;
1926 return_cmd_error(STR_ERROR_CAN_T_REVERSE_DIRECTION_RAIL_VEHICLE_MULTIPLE_UNITS);
1953 while (last->
Next() != NULL) last = last->
Next();
1995 if (ret.
Failed())
return ret;
2031 default: NOT_REACHED();
2047 if (location != NULL) *location = tfdd.
tile;
2049 if (reverse != NULL) *reverse = tfdd.
reverse;
2057 static const SoundFx sfx[] = {
2068 SndPlayVehicleFx(sfx[RailVehInfo(engtype)->engclass],
this);
2089 case OT_GOTO_WAYPOINT:
2095 case OT_LEAVESTATION:
2140 for (
const Train *u = v; u != NULL; u = u->
Next()) {
2153 if (v->force_proceed ==
TFP_NONE) {
2273 for (
const Train *u = v; u != NULL; u = u->
Next()) {
2281 while (ft.
Follow(tile, td)) {
2316 static const byte _initial_tile_subcoord[6][4][3] = {
2317 {{ 15, 8, 1 }, { 0, 0, 0 }, { 0, 8, 5 }, { 0, 0, 0 }},
2318 {{ 0, 0, 0 }, { 8, 0, 3 }, { 0, 0, 0 }, { 8, 15, 7 }},
2319 {{ 0, 0, 0 }, { 7, 0, 2 }, { 0, 7, 6 }, { 0, 0, 0 }},
2320 {{ 15, 8, 2 }, { 0, 0, 0 }, { 0, 0, 0 }, { 8, 15, 6 }},
2321 {{ 15, 7, 0 }, { 8, 0, 4 }, { 0, 0, 0 }, { 0, 0, 0 }},
2322 {{ 0, 0, 0 }, { 0, 0, 0 }, { 0, 8, 4 }, { 7, 15, 0 }},
2343 default: NOT_REACHED();
2360 while (ft.
Follow(tile, cur_td)) {
2388 if (enterdir != NULL) *enterdir = ft.
m_exitdir;
2405 if (ft.m_err == CFollowTrackRail::EC_OWNER || ft.m_err == CFollowTrackRail::EC_NO_WAY) {
2415 while (tile != stopped || cur_td != stopped_td) {
2416 if (!ft.
Follow(tile, cur_td))
break;
2450 default: NOT_REACHED();
2460 StationID old_last_station_visited;
2462 bool suppress_implicit_orders;
2478 this->v->
dest_tile = this->old_dest_tile;
2492 if (skip_first) ++this->index;
2498 if (this->index >= this->v->
GetNumOrders()) this->index = 0;
2501 assert(order != NULL);
2507 case OT_GOTO_STATION:
2508 case OT_GOTO_WAYPOINT:
2511 case OT_CONDITIONAL: {
2539 bool changed_signal =
false;
2543 if (got_reservation != NULL) *got_reservation =
false;
2555 do_track_reservation =
true;
2556 changed_signal =
true;
2558 }
else if (!do_track_reservation) {
2566 if (do_track_reservation) {
2574 if (res_dest.okay) {
2576 if (got_reservation != NULL) *got_reservation =
true;
2599 orders.SwitchToNextOrder(
false);
2603 v->tile == v->dest_tile))) {
2604 orders.SwitchToNextOrder(
true);
2609 bool path_found =
true;
2612 Track next_track =
DoTrainPathfind(v, new_tile, dest_enterdir, tracks, path_found, do_track_reservation, &res_dest);
2613 if (new_tile == tile) best_track = next_track;
2618 if (!do_track_reservation)
return best_track;
2635 if (got_reservation != NULL) *got_reservation =
true;
2644 if (got_reservation != NULL) *got_reservation =
true;
2657 if (orders.SwitchToNextOrder(
true)) {
2660 DoTrainPathfind(v, next_tile, exitdir, reachable, path_found,
true, &cur_dest);
2662 res_dest = cur_dest;
2663 if (res_dest.okay)
continue;
2667 if (got_reservation != NULL) *got_reservation =
false;
2668 changed_signal =
false;
2676 if (got_reservation != NULL) *got_reservation =
false;
2677 changed_signal =
false;
2722 if (other_train != NULL && other_train->
index != v->
index) {
2727 if (origin.
okay && (v->
tile != origin.
tile || first_tile_okay)) {
2746 bool res_made =
false;
2747 ChooseTrainTrack(v, new_tile, exitdir, reachable,
true, &res_made, mark_as_stuck);
2764 static bool CheckReverseTrain(
const Train *v)
2778 default: NOT_REACHED();
2808 }
while ((v = v->
Next()) != NULL);
2825 default: NOT_REACHED();
2845 if (!(st->had_vehicle_of_type &
HVOT_TRAIN)) {
2849 STR_NEWS_FIRST_TRAIN_ARRIVAL,
2868 static inline bool CheckCompatibleRail(
const Train *v,
TileIndex tile)
2885 {256 / 4, 256 / 2, 256 / 4, 2},
2886 {256 / 4, 256 / 2, 256 / 4, 2},
2887 {0, 256 / 2, 256 / 4, 2},
2901 if (old_z < v->z_pos) {
2905 if (spd <= v->gcache.cached_max_track_speed) v->
cur_speed = spd;
2917 if (!IsPbsSignal(GetSignalType(tile,
TrackdirToTrack(trackdir))))
return true;
2926 for (
const Train *u =
this; u != NULL; u = u->
Next()) {
2955 for (
const Train *v =
this; v != NULL; v = v->
Next()) {
3029 if (coll == tcc->
v)
return NULL;
3038 uint hash = (y_diff + 7) | (x_diff + 7);
3039 if (hash & ~15)
return NULL;
3043 if (x_diff * x_diff + y_diff * y_diff > min_diff * min_diff)
return NULL;
3082 if (tcc.
num == 0)
return false;
3087 ModifyStationRatingAround(v->
tile, v->
owner, -160, 30);
3118 bool direction_changed =
false;
3121 for (prev = v->
Previous(); v != nomove; prev = v, v = v->
Next()) {
3123 bool update_signals_crossing =
false;
3175 if (!CheckCompatibleRail(v, gp.
new_tile))
goto invalid_rail;
3201 if ((red_signals & chosen_track) && v->force_proceed ==
TFP_NONE) {
3211 v->progress = 255 - 100;
3216 v->progress = 255 - 10;
3224 if (!
HasVehicleOnPos(o_tile, &exitdir, &CheckTrainAtSignal))
return false;
3234 v->wait_counter = 0;
3237 goto reverse_train_direction;
3249 chosen_track = bits;
3251 chosen_track = prev->track;
3269 chosen_track = _connecting_track[enterdir][exitdir];
3271 chosen_track &= bits;
3281 const byte *b = _initial_tile_subcoord[
FIND_FIRST_BIT(chosen_track)][enterdir];
3282 gp.x = (gp.x & ~0xF) | b[0];
3283 gp.
y = (gp.
y & ~0xF) | b[1];
3309 v->track = chosen_track;
3315 update_signals_crossing =
true;
3317 if (chosen_dir != v->direction) {
3323 direction_changed =
true;
3324 v->direction = chosen_dir;
3327 if (v->IsFrontEngine()) {
3328 v->wait_counter = 0;
3346 if (v->IsFrontEngine()) {
3358 v->UpdatePosition();
3359 if ((v->vehstatus &
VS_HIDDEN) == 0) v->Vehicle::UpdateViewport(
true);
3365 v->UpdateDeltaXY(v->direction);
3369 v->UpdatePosition();
3379 if (update_signals_crossing) {
3380 if (v->IsFrontEngine()) {
3381 if (TrainMovedChangeSignals(gp.
new_tile, enterdir)) {
3400 if (v->Next() == NULL) {
3416 if (prev != NULL)
error(
"Disconnecting train");
3418 reverse_train_direction:
3420 v->wait_counter = 0;
3445 *trackbits |= train_tbits;
3467 for (; v->
Next() != NULL; v = v->
Next()) u = v;
3525 static const DirDiff delta[] = {
3543 }
while ((v = v->
Next()) != NULL);
3560 if (state <= 200 &&
Chance16R(1, 7, r)) {
3561 int index = (r * 10 >> 16);
3575 }
while ((u = u->
Next()) != NULL);
3581 bool ret = v->
Next() != NULL;
3591 225, 210, 195, 180, 165, 150, 135, 120, 105, 90, 75, 60, 45, 30, 15, 15
3606 uint x = v->
x_pos & 0xF;
3607 uint y = v->
y_pos & 0xF;
3612 case DIR_N : x = ~x + ~y + 25;
break;
3614 case DIR_NE: x = ~x + 16;
break;
3615 case DIR_E : x = ~x + y + 9;
break;
3616 case DIR_SE: x = y;
break;
3617 case DIR_S : x = x + y - 7;
break;
3618 case DIR_W : x = ~y + x + 9;
break;
3636 uint16 break_speed = _breakdown_speeds[x & 0xF];
3637 if (break_speed < v->cur_speed) v->
cur_speed = break_speed;
3690 !CheckCompatibleRail(v, tile)) {
3713 uint16 break_speed = _breakdown_speeds[
GB(~t, 4, 4)];
3714 if (break_speed < v->cur_speed) v->
cur_speed = break_speed;
3756 static bool TrainLocoHandler(
Train *v,
bool mode)
3763 if (v->force_proceed !=
TFP_NONE) {
3833 if (v->force_proceed ==
TFP_NONE)
return true;
3871 if (j < adv_spd || v->cur_speed == 0)
break;
3875 if ((order_type == OT_GOTO_WAYPOINT || order_type == OT_GOTO_STATION) &&
3885 for (
Train *u = v; u != NULL; u = u->
Next()) {
3903 const Train *v =
this;
3907 if (e->u.rail.running_cost_class == INVALID_PRICE)
continue;
3910 if (cost_factor == 0)
continue;
3915 cost +=
GetPrice(e->u.rail.running_cost_class, cost_factor, e->
GetGRF());
3934 if (!TrainLocoHandler(
this,
false))
return false;
3936 return TrainLocoHandler(
this,
true);
3964 default: NOT_REACHED();
4002 CheckVehicleBreakdown(
this);