39 #include "table/strings.h"
43 static const uint16 _roadveh_images[] = {
44 0xCD4, 0xCDC, 0xCE4, 0xCEC, 0xCF4, 0xCFC, 0xD0C, 0xD14,
45 0xD24, 0xD1C, 0xD2C, 0xD04, 0xD1C, 0xD24, 0xD6C, 0xD74,
46 0xD7C, 0xC14, 0xC1C, 0xC24, 0xC2C, 0xC34, 0xC3C, 0xC4C,
47 0xC54, 0xC64, 0xC5C, 0xC6C, 0xC44, 0xC5C, 0xC64, 0xCAC,
48 0xCB4, 0xCBC, 0xD94, 0xD9C, 0xDA4, 0xDAC, 0xDB4, 0xDBC,
49 0xDCC, 0xDD4, 0xDE4, 0xDDC, 0xDEC, 0xDC4, 0xDDC, 0xDE4,
50 0xE2C, 0xE34, 0xE3C, 0xC14, 0xC1C, 0xC2C, 0xC3C, 0xC4C,
51 0xC5C, 0xC64, 0xC6C, 0xC74, 0xC84, 0xC94, 0xCA4
54 static const uint16 _roadveh_full_adder[] = {
55 0, 88, 0, 0, 0, 0, 48, 48,
56 48, 48, 0, 0, 64, 64, 0, 16,
57 16, 0, 88, 0, 0, 0, 0, 48,
58 48, 48, 48, 0, 0, 64, 64, 0,
59 16, 16, 0, 88, 0, 0, 0, 0,
60 48, 48, 48, 48, 0, 0, 64, 64,
61 0, 16, 16, 0, 8, 8, 8, 8,
67 bool IsValidImageIndex<VEH_ROAD>(uint8 image_index)
69 return image_index <
lengthof(_roadveh_images);
107 int reference_width = ROADVEHINFO_DEFAULT_VEHICLE_WIDTH;
109 if (offset != NULL) {
110 offset->x =
UnScaleByZoom(2 * reference_width, ZOOM_LVL_GUI);
121 if (is_custom_sprite(spritenum)) {
122 SpriteID sprite = GetCustomVehicleIcon(engine,
DIR_W, image_type);
123 if (sprite != 0)
return sprite;
128 assert(IsValidImageIndex<VEH_ROAD>(spritenum));
137 if (is_custom_sprite(spritenum)) {
138 sprite = GetCustomVehicleSprite(
this, (
Direction)(direction + 4 * IS_CUSTOM_SECONDHEAD_SPRITE(spritenum)), image_type);
139 if (sprite != 0)
return sprite;
144 assert(IsValidImageIndex<VEH_ROAD>(spritenum));
145 sprite = direction + _roadveh_images[
spritenum];
163 SpriteID sprite = GetRoadVehIcon(engine, image_type);
180 const Sprite *spr = GetSprite(GetRoadVehIcon(engine, image_type),
ST_NORMAL);
199 if (e->
GetGRF() != NULL && e->
GetGRF()->grf_version >= 8) {
232 assert(u->First() == v);
242 u->gcache.cached_veh_length = veh_len;
246 u->UpdateVisualEffect();
282 v->
z_pos = GetSlopePixelZ(x, y);
300 _new_vehicle_id = v->
index;
323 u->cargo_cap = u->GetEngine()->DetermineCapacity(u);
326 u->InvalidateNewGRFCache();
348 default: NOT_REACHED();
357 if (location != NULL) *location = rfdd.
tile;
380 if (ret.
Failed())
return ret;
396 if (flags &
DC_EXEC) v->reverse_ctr = 180;
413 static const int8 _delta_xy_table[8][10] = {
415 {3, 3, -1, -1, 0, 0, -1, -1, -1, -1},
416 {3, 7, -1, -3, 0, -1, 0, -1, 0, 0},
417 {3, 3, -1, -1, 0, 0, 1, -1, 1, -1},
418 {7, 3, -3, -1, -1, 0, 0, 0, 1, 0},
419 {3, 3, -1, -1, 0, 0, 1, 1, 1, 1},
420 {3, 7, -1, -3, 0, -1, 0, 0, 0, 1},
421 {3, 3, -1, -1, 0, 0, -1, 1, -1, 1},
422 {7, 3, -3, -1, -1, 0, -1, 0, 0, 0},
428 const int8 *bb = _delta_xy_table[
direction];
429 this->
x_bb_offs = bb[5] + bb[9] * shorten;
430 this->
y_bb_offs = bb[4] + bb[8] * shorten;;
433 this->
x_extent = bb[1] + bb[7] * shorten;
434 this->
y_extent = bb[0] + bb[6] * shorten;
452 }
else if ((u->direction & 1) == 0) {
474 for (; v->
Next() != NULL; v = v->
Next()) u = v;
484 static void RoadVehSetRandomDirection(
RoadVehicle *v)
486 static const DirDiff delta[] = {
495 }
while ((v = v->
Next()) != NULL);
509 if ((v->
tick_counter & 7) == 0) RoadVehSetRandomDirection(v);
511 bool ret = v->
Next() != NULL;
552 uint pass = v->
Crash();
555 Game::NewEvent(
new ScriptEventVehicleCrashed(v->
index, v->
tile, ScriptEventVehicleCrashed::CRASH_RV_LEVEL_CROSSING));
560 STR_NEWS_ROAD_VEHICLE_CRASH_DRIVER : STR_NEWS_ROAD_VEHICLE_CRASH,
565 ModifyStationRatingAround(v->
tile, v->
owner, -160, 22);
601 static void StartRoadVehSound(
const RoadVehicle *v)
605 if (s == SND_19_BUS_START_PULL_AWAY && (v->
tick_counter & 3) == 0) {
606 s = SND_1A_BUS_START_PULL_AWAY_WITH_HORN;
608 SndPlayVehicleFx(s, v);
623 static const int8 dist_x[] = { -4, -8, -4, -1, 4, 8, 4, 1 };
624 static const int8 dist_y[] = { -4, -1, 4, 8, 4, 1, -4, -8 };
628 short x_diff = v->
x_pos - rvf->x;
629 short y_diff = v->
y_pos - rvf->y;
640 uint diff =
abs(x_diff) +
abs(y_diff);
642 if (diff < rvf->best_diff || (diff == rvf->best_diff && v->
index < rvf->best->
index)) {
644 rvf->best_diff = diff;
656 if (front->reverse_ctr != 0)
return NULL;
662 rvf.best_diff = UINT_MAX;
675 if (rvf.best_diff == UINT_MAX) {
676 front->blocked_ctr = 0;
680 if (update_blocked_ctr && ++front->blocked_ctr > 1480)
return NULL;
694 if (!(st->had_vehicle_of_type &
HVOT_BUS)) {
695 st->had_vehicle_of_type |=
HVOT_BUS;
698 v->roadtype ==
ROADTYPE_ROAD ? STR_NEWS_FIRST_BUS_ARRIVAL : STR_NEWS_FIRST_PASSENGER_TRAM_ARRIVAL,
708 if (!(st->had_vehicle_of_type &
HVOT_TRUCK)) {
712 v->roadtype ==
ROADTYPE_ROAD ? STR_NEWS_FIRST_TRUCK_ARRIVAL : STR_NEWS_FIRST_CARGO_TRAM_ARRIVAL,
733 default: NOT_REACHED();
744 static const Direction _roadveh_new_dir[] = {
750 x = x - v->
x_pos + 1;
751 y = y - v->
y_pos + 1;
753 if ((uint)x > 2 || (uint)y > 2)
return v->
direction;
754 return _roadveh_new_dir[y * 4 + x];
759 Direction new_dir = RoadVehGetNewDirection(v, x, y);
763 if (new_dir == old_dir)
return old_dir;
775 static Vehicle *EnumFindVehBlockingOvertake(
Vehicle *v,
void *data)
779 return (v->
type ==
VEH_ROAD && v->
First() == v && v != od->u && v != od->v) ? v : NULL;
850 static void RoadZPosAffectSpeed(
RoadVehicle *v,
int old_z)
854 if (old_z < v->z_pos) {
858 if (spd <= v->vcache.cached_max_speed) v->
cur_speed = spd;
862 static int PickRandomBit(uint bits)
867 for (i = 0; !(bits & 1) || (
int)--num >= 0; bits >>= 1, i++) {}
881 #define return_track(x) { best_track = (Trackdir)x; goto found_best_track; }
885 bool path_found =
true;
925 trackdirs &= _road_enter_dir_to_reachable_trackdirs[enterdir];
928 return_track(_road_reverse_table[enterdir]);
931 if (v->reverse_ctr != 0) {
938 reverse = ((rb & straight) == straight) ||
943 if (v->
tile != tile) {
944 return_track(_road_reverse_table[enterdir]);
952 return_track(PickRandomBit(trackdirs));
964 default: NOT_REACHED();
981 static bool RoadVehLeaveDepot(
RoadVehicle *v,
bool first)
991 Trackdir tdir = _roadveh_depot_exit_trackdir[dir];
1004 if (RoadVehFindCloseTo(v, x, y, v->
direction,
false) != NULL)
return true;
1008 StartRoadVehSound(v);
1016 v->frame = RVC_DEPOT_START_FRAME;
1030 if (prev->
tile == v->
tile && !already_reversed) {
1033 return _road_reverse_table[entry_dir];
1036 byte prev_state = prev->
state;
1051 if (already_reversed && prev->
tile != tile) {
1081 static const RoadBits required_roadbits[] = {
1085 RoadBits required = required_roadbits[dir & 0x07];
1176 dir = FollowPreviousRoadVehicle(v, prev, tile, (
DiagDirection)(rd.x & 3),
false);
1186 uint start_frame = RVC_DEFAULT_START_FRAME;
1197 default: NOT_REACHED();
1229 start_frame = RVC_TURN_AROUND_START_FRAME_SHORT_TRAM;
1249 Direction new_dir = RoadVehGetSlidingDirection(v, x, y);
1251 Vehicle *u = RoadVehFindCloseTo(v, x, y, new_dir);
1265 dir = _road_reverse_table[rd.x & 3];
1297 v->
state = (byte)dir;
1298 v->frame = start_frame;
1314 uint turn_around_start_frame = RVC_TURN_AROUND_START_FRAME;
1326 turn_around_start_frame = RVC_START_FRAME_AFTER_LONG_TRAM;
1327 switch (rd.x & 0x3) {
1328 default: NOT_REACHED();
1339 dir = FollowPreviousRoadVehicle(v, prev, v->
tile, (
DiagDirection)(rd.x & 3),
true);
1353 Direction new_dir = RoadVehGetSlidingDirection(v, x, y);
1354 if (v->
IsFrontEngine() && RoadVehFindCloseTo(v, x, y, new_dir) != NULL)
return false;
1363 v->frame = turn_around_start_frame;
1382 RoadVehLeaveDepot(v->
Next(),
false);
1387 int x = (v->
x_pos & ~15) + (rd.x & 15);
1388 int y = (v->
y_pos & ~15) + (rd.y & 15);
1390 Direction new_dir = RoadVehGetSlidingDirection(v, x, y);
1395 RoadVehicle *u = RoadVehFindCloseTo(v, x, y, new_dir);
1400 if (v->
overtaking == 0) RoadVehCheckOvertake(v, u);
1418 if (new_dir != old_dir) {
1441 v->frame == RVC_DRIVE_THROUGH_STOP_FRAME))) {
1488 StartRoadVehSound(v);
1518 if (v->reverse_ctr != 0) v->reverse_ctr--;
1534 if (v->
IsInDepot() && RoadVehLeaveDepot(v,
true))
return true;
1542 bool blocked =
false;
1543 while (j >= adv_spd) {
1548 if (!IndividualRoadVehicleController(u, prev)) {
1559 if (j >= adv_spd && RoadVehCheckTrainCrash(v))
break;
1565 if ((u->vehstatus &
VS_HIDDEN) != 0)
continue;
1567 u->UpdateViewport(
false,
false);
1581 if (e->u.road.running_cost_class == INVALID_PRICE)
return 0;
1584 if (cost_factor == 0)
return 0;
1586 return GetPrice(e->u.road.running_cost_class, cost_factor, e->
GetGRF());
1595 return RoadVehController(
this);
1601 static void CheckIfRoadVehNeedsService(
RoadVehicle *v)
1614 default: NOT_REACHED();
1651 if (this->blocked_ctr == 0) CheckVehicleBreakdown(
this);
1653 CheckIfRoadVehNeedsService(
this);