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) {
467 offset->x =
UnScaleByZoom(2 * reference_width, ZOOM_LVL_GUI);
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);
546 SpriteID sprite = GetRailIcon(engine,
false, y, image_type);
566 SpriteID sprite = GetRailIcon(engine,
false, y, image_type);
575 sprite = GetRailIcon(engine,
true, y, image_type);
576 real_sprite = GetSprite(sprite,
ST_NORMAL);
581 xoffs = xoffs -
UnScaleByZoom(TRAININFO_DEFAULT_VEHICLE_WIDTH * 4, ZOOM_LVL_GUI) / 2;
619 v->
z_pos = GetSlopePixelZ(x, y);
633 v->railtype = rvi->railtype;
643 _new_vehicle_id = v->
index;
654 if (w->
tile == tile &&
682 static void AddRearEngineToMultiheadedTrain(
Train *v)
700 u->railtype = v->railtype;
711 v->other_multiheaded_part = u;
712 u->other_multiheaded_part = v;
746 v->
z_pos = GetSlopePixelZ(x, y);
763 v->railtype = rvi->railtype;
764 _new_vehicle_id = v->
index;
783 AddRearEngineToMultiheadedTrain(v);
801 static Train *FindGoodVehiclePos(
const Train *src)
807 FOR_ALL_TRAINS(dst) {
813 if (t == NULL)
return dst;
831 for (; t != NULL; t = t->
Next()) *list.
Append() = t;
841 if (list.
Length() == 0)
return;
845 for (
Train **iter = list.
Begin(); iter != list.
End(); iter++) {
902 if (u == t->other_multiheaded_part)
continue;
918 if (chain == NULL)
return;
952 if ((src != NULL && src->
IsEngine() ? 1 : 0) +
953 (dst != NULL && dst->
IsEngine() ? 1 : 0) -
954 (original_src != NULL && original_src->
IsEngine() ? 1 : 0) -
955 (original_dst != NULL && original_dst->
IsEngine() ? 1 : 0) <= 0) {
1022 if (head->
GetGRF()->grf_version < 8) {
1023 if (callback == 0xFD) error = STR_ERROR_INCOMPATIBLE_RAIL_TYPES;
1027 if (callback < 0x400) {
1037 error = STR_ERROR_INCOMPATIBLE_RAIL_TYPES;
1071 if (ret.
Failed())
return ret;
1073 if (ret.
Failed())
return ret;
1090 if (*src_head == *dst_head) {
1094 }
else if (*dst_head == NULL) {
1100 if (src == *src_head) {
1107 *src_head = move_chain ? NULL :
1131 if (head == NULL)
return;
1165 bool move_chain =
HasBit(p1, 20);
1171 if (ret.
Failed())
return ret;
1179 dst = src->
IsEngine() ? NULL : FindGoodVehiclePos(src);
1185 if (ret.
Failed())
return ret;
1204 dst_head = dst->
First();
1215 if (move_chain && src_head == dst_head)
return CommandCost();
1228 TrainList original_src;
1229 TrainList original_dst;
1237 Train *original_src_head = src_head;
1238 Train *original_dst_head = (dst_head == src_head ? NULL : dst_head);
1243 bool original_src_head_front_engine = original_src_head->
IsFrontEngine();
1244 bool original_dst_head_front_engine = original_dst_head != NULL && original_dst_head->
IsFrontEngine();
1311 if (original_src_head != src && dst_head == src) {
1358 bool sell_chain =
HasBit(data, 0);
1372 Train *sell_head = NULL;
1440 static const int _sign_table[] =
1453 this->
y_offs -= half_shorten * _sign_table[direction + 1];
1457 switch (direction) {
1522 uint16 flag1 = *swap_flag1;
1523 uint16 flag2 = *swap_flag2;
1590 for (a = v; l != 0; l--) a = a->
Next();
1591 for (b = v; r != 0; r--) b = b->
Next();
1601 Swap(a->track, b->track);
1690 if (new_state && sound) {
1724 uint length = CountVehiclesInChain(v);
1726 while (length > 2) {
1728 first = first->
Next();
1757 if (leave != NULL) {
1773 uint length = CountVehiclesInChain(v);
1777 bool nomove = (dep == NULL);
1779 while (length > 2) {
1782 if (base == dep)
break;
1785 if (last == dep) nomove =
true;
1788 first = first->
Next();
1793 for (
int i = 0; i < differential; i++)
TrainController(first, (nomove ? last->
Next() : NULL));
1817 int r = CountVehiclesInChain(v) - 1;
1835 ClrBit(v->flags, VRF_REVERSING);
1903 if (ret.
Failed())
return ret;
1909 return_cmd_error(STR_ERROR_CAN_T_REVERSE_DIRECTION_RAIL_VEHICLE_MULTIPLE_UNITS);
1936 while (last->
Next() != NULL) last = last->
Next();
1978 if (ret.
Failed())
return ret;
2014 default: NOT_REACHED();
2030 if (location != NULL) *location = tfdd.
tile;
2032 if (reverse != NULL) *reverse = tfdd.
reverse;
2040 static const SoundFx sfx[] = {
2051 SndPlayVehicleFx(sfx[RailVehInfo(engtype)->engclass],
this);
2072 case OT_GOTO_WAYPOINT:
2078 case OT_LEAVESTATION:
2123 for (
const Train *u = v; u != NULL; u = u->
Next()) {
2136 if (v->force_proceed ==
TFP_NONE) {
2252 for (
const Train *u = v; u != NULL; u = u->
Next()) {
2260 while (ft.
Follow(tile, td)) {
2295 static const byte _initial_tile_subcoord[6][4][3] = {
2296 {{ 15, 8, 1 }, { 0, 0, 0 }, { 0, 8, 5 }, { 0, 0, 0 }},
2297 {{ 0, 0, 0 }, { 8, 0, 3 }, { 0, 0, 0 }, { 8, 15, 7 }},
2298 {{ 0, 0, 0 }, { 7, 0, 2 }, { 0, 7, 6 }, { 0, 0, 0 }},
2299 {{ 15, 8, 2 }, { 0, 0, 0 }, { 0, 0, 0 }, { 8, 15, 6 }},
2300 {{ 15, 7, 0 }, { 8, 0, 4 }, { 0, 0, 0 }, { 0, 0, 0 }},
2301 {{ 0, 0, 0 }, { 0, 0, 0 }, { 0, 8, 4 }, { 7, 15, 0 }},
2322 default: NOT_REACHED();
2339 while (ft.
Follow(tile, cur_td)) {
2367 if (enterdir != NULL) *enterdir = ft.
m_exitdir;
2384 if (ft.m_err == CFollowTrackRail::EC_OWNER || ft.m_err == CFollowTrackRail::EC_NO_WAY) {
2394 while (tile != stopped || cur_td != stopped_td) {
2395 if (!ft.
Follow(tile, cur_td))
break;
2429 default: NOT_REACHED();
2439 StationID old_last_station_visited;
2441 bool suppress_implicit_orders;
2457 this->v->
dest_tile = this->old_dest_tile;
2471 if (skip_first) ++this->index;
2477 if (this->index >= this->v->
GetNumOrders()) this->index = 0;
2480 assert(order != NULL);
2486 case OT_GOTO_STATION:
2487 case OT_GOTO_WAYPOINT:
2490 case OT_CONDITIONAL: {
2518 bool changed_signal =
false;
2522 if (got_reservation != NULL) *got_reservation =
false;
2534 do_track_reservation =
true;
2535 changed_signal =
true;
2537 }
else if (!do_track_reservation) {
2545 if (do_track_reservation) {
2553 if (res_dest.okay) {
2555 if (got_reservation != NULL) *got_reservation =
true;
2578 orders.SwitchToNextOrder(
false);
2582 v->tile == v->dest_tile))) {
2583 orders.SwitchToNextOrder(
true);
2588 bool path_found =
true;
2591 Track next_track =
DoTrainPathfind(v, new_tile, dest_enterdir, tracks, path_found, do_track_reservation, &res_dest);
2592 if (new_tile == tile) best_track = next_track;
2597 if (!do_track_reservation)
return best_track;
2614 if (got_reservation != NULL) *got_reservation =
true;
2623 if (got_reservation != NULL) *got_reservation =
true;
2636 if (orders.SwitchToNextOrder(
true)) {
2639 DoTrainPathfind(v, next_tile, exitdir, reachable, path_found,
true, &cur_dest);
2641 res_dest = cur_dest;
2642 if (res_dest.okay)
continue;
2646 if (got_reservation != NULL) *got_reservation =
false;
2647 changed_signal =
false;
2655 if (got_reservation != NULL) *got_reservation =
false;
2656 changed_signal =
false;
2701 if (other_train != NULL && other_train->
index != v->
index) {
2706 if (origin.
okay && (v->
tile != origin.
tile || first_tile_okay)) {
2725 bool res_made =
false;
2726 ChooseTrainTrack(v, new_tile, exitdir, reachable,
true, &res_made, mark_as_stuck);
2743 static bool CheckReverseTrain(
const Train *v)
2757 default: NOT_REACHED();
2787 }
while ((v = v->
Next()) != NULL);
2804 default: NOT_REACHED();
2824 if (!(st->had_vehicle_of_type &
HVOT_TRAIN)) {
2828 STR_NEWS_FIRST_TRAIN_ARRIVAL,
2847 static inline bool CheckCompatibleRail(
const Train *v,
TileIndex tile)
2864 {256 / 4, 256 / 2, 256 / 4, 2},
2865 {256 / 4, 256 / 2, 256 / 4, 2},
2866 {0, 256 / 2, 256 / 4, 2},
2880 if (old_z < v->z_pos) {
2884 if (spd <= v->gcache.cached_max_track_speed) v->
cur_speed = spd;
2896 if (!IsPbsSignal(GetSignalType(tile,
TrackdirToTrack(trackdir))))
return true;
2905 for (
const Train *u =
this; u != NULL; u = u->
Next()) {
2934 for (
const Train *v =
this; v != NULL; v = v->
Next()) {
3008 if (coll == tcc->
v)
return NULL;
3017 uint hash = (y_diff + 7) | (x_diff + 7);
3018 if (hash & ~15)
return NULL;
3022 if (x_diff * x_diff + y_diff * y_diff > min_diff * min_diff)
return NULL;
3061 if (tcc.
num == 0)
return false;
3066 ModifyStationRatingAround(v->
tile, v->
owner, -160, 30);
3097 bool direction_changed =
false;
3100 for (prev = v->
Previous(); v != nomove; prev = v, v = v->
Next()) {
3102 bool update_signals_crossing =
false;
3154 if (!CheckCompatibleRail(v, gp.
new_tile))
goto invalid_rail;
3180 if ((red_signals & chosen_track) && v->force_proceed ==
TFP_NONE) {
3190 v->progress = 255 - 100;
3195 v->progress = 255 - 10;
3203 if (!
HasVehicleOnPos(o_tile, &exitdir, &CheckTrainAtSignal))
return false;
3213 v->wait_counter = 0;
3216 goto reverse_train_direction;
3228 chosen_track = bits;
3230 chosen_track = prev->track;
3248 chosen_track = _connecting_track[enterdir][exitdir];
3250 chosen_track &= bits;
3260 const byte *b = _initial_tile_subcoord[
FIND_FIRST_BIT(chosen_track)][enterdir];
3261 gp.x = (gp.x & ~0xF) | b[0];
3262 gp.
y = (gp.
y & ~0xF) | b[1];
3288 v->track = chosen_track;
3294 update_signals_crossing =
true;
3296 if (chosen_dir != v->direction) {
3302 direction_changed =
true;
3303 v->direction = chosen_dir;
3306 if (v->IsFrontEngine()) {
3307 v->wait_counter = 0;
3325 if (v->IsFrontEngine()) {
3337 v->UpdatePosition();
3338 if ((v->vehstatus &
VS_HIDDEN) == 0) v->Vehicle::UpdateViewport(
true);
3344 v->UpdateDeltaXY(v->direction);
3348 v->UpdatePosition();
3358 if (update_signals_crossing) {
3359 if (v->IsFrontEngine()) {
3360 if (TrainMovedChangeSignals(gp.
new_tile, enterdir)) {
3379 if (v->Next() == NULL) {
3395 if (prev != NULL)
error(
"Disconnecting train");
3397 reverse_train_direction:
3399 v->wait_counter = 0;
3424 *trackbits |= train_tbits;
3446 for (; v->
Next() != NULL; v = v->
Next()) u = v;
3504 static const DirDiff delta[] = {
3522 }
while ((v = v->
Next()) != NULL);
3539 if (state <= 200 &&
Chance16R(1, 7, r)) {
3540 int index = (r * 10 >> 16);
3554 }
while ((u = u->
Next()) != NULL);
3560 bool ret = v->
Next() != NULL;
3570 225, 210, 195, 180, 165, 150, 135, 120, 105, 90, 75, 60, 45, 30, 15, 15
3585 uint x = v->
x_pos & 0xF;
3586 uint y = v->
y_pos & 0xF;
3591 case DIR_N : x = ~x + ~y + 25;
break;
3593 case DIR_NE: x = ~x + 16;
break;
3594 case DIR_E : x = ~x + y + 9;
break;
3595 case DIR_SE: x = y;
break;
3596 case DIR_S : x = x + y - 7;
break;
3597 case DIR_W : x = ~y + x + 9;
break;
3615 uint16 break_speed = _breakdown_speeds[x & 0xF];
3616 if (break_speed < v->cur_speed) v->
cur_speed = break_speed;
3669 !CheckCompatibleRail(v, tile)) {
3692 uint16 break_speed = _breakdown_speeds[
GB(~t, 4, 4)];
3693 if (break_speed < v->cur_speed) v->
cur_speed = break_speed;
3735 static bool TrainLocoHandler(
Train *v,
bool mode)
3742 if (v->force_proceed !=
TFP_NONE) {
3812 if (v->force_proceed ==
TFP_NONE)
return true;
3850 if (j < adv_spd || v->cur_speed == 0)
break;
3854 if ((order_type == OT_GOTO_WAYPOINT || order_type == OT_GOTO_STATION) &&
3864 for (
Train *u = v; u != NULL; u = u->
Next()) {
3882 const Train *v =
this;
3886 if (e->u.rail.running_cost_class == INVALID_PRICE)
continue;
3889 if (cost_factor == 0)
continue;
3894 cost +=
GetPrice(e->u.rail.running_cost_class, cost_factor, e->
GetGRF());
3913 if (!TrainLocoHandler(
this,
false))
return false;
3915 return TrainLocoHandler(
this,
true);
3943 default: NOT_REACHED();
3981 CheckVehicleBreakdown(
this);