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) {
 
  121   if (is_custom_sprite(spritenum)) {
 
  122     GetCustomVehicleIcon(engine, 
DIR_W, image_type, result);
 
  128   assert(IsValidImageIndex<VEH_ROAD>(spritenum));
 
  129   result->
Set(
DIR_W + _roadveh_images[spritenum]);
 
  136   if (is_custom_sprite(spritenum)) {
 
  137     GetCustomVehicleSprite(
this, (
Direction)(direction + 4 * IS_CUSTOM_SECONDHEAD_SPRITE(spritenum)), image_type, result);
 
  143   assert(IsValidImageIndex<VEH_ROAD>(spritenum));
 
  163   GetRoadVehIcon(engine, image_type, &seq);
 
  167   preferred_x = 
Clamp(preferred_x,
 
  186   GetRoadVehIcon(engine, image_type, &seq);
 
  191   width  = 
UnScaleGUI(rect.right - rect.left + 1);
 
  192   height = 
UnScaleGUI(rect.bottom - rect.top + 1);
 
  208   if (e->
GetGRF() != NULL && e->
GetGRF()->grf_version >= 8) {
 
  241     assert(u->First() == v);
 
  251     u->gcache.cached_veh_length = veh_len;
 
  255     u->UpdateVisualEffect();
 
  291     v->
z_pos = GetSlopePixelZ(x, y);
 
  309     _new_vehicle_id = v->
index;
 
  332       u->cargo_cap = u->GetEngine()->DetermineCapacity(u);
 
  335       u->InvalidateNewGRFCache();
 
  357     default: NOT_REACHED();
 
  366   if (location    != NULL) *location    = rfdd.
tile;
 
  389   if (ret.
Failed()) 
return ret;
 
  405   if (flags & 
DC_EXEC) v->reverse_ctr = 180;
 
  422   static const int8 _delta_xy_table[8][10] = {
 
  424     {3, 3, -1, -1,  0,  0, -1, -1, -1, -1}, 
 
  425     {3, 7, -1, -3,  0, -1,  0, -1,  0,  0}, 
 
  426     {3, 3, -1, -1,  0,  0,  1, -1,  1, -1}, 
 
  427     {7, 3, -3, -1, -1,  0,  0,  0,  1,  0}, 
 
  428     {3, 3, -1, -1,  0,  0,  1,  1,  1,  1}, 
 
  429     {3, 7, -1, -3,  0, -1,  0,  0,  0,  1}, 
 
  430     {3, 3, -1, -1,  0,  0, -1,  1, -1,  1}, 
 
  431     {7, 3, -3, -1, -1,  0, -1,  0,  0,  0}, 
 
  437   const int8 *bb = _delta_xy_table[
direction];
 
  438   this->
x_bb_offs     = bb[5] + bb[9] * shorten;
 
  439   this->
y_bb_offs     = bb[4] + bb[8] * shorten;;
 
  442   this->
x_extent      = bb[1] + bb[7] * shorten;
 
  443   this->
y_extent      = bb[0] + bb[6] * shorten;
 
  461       } 
else if ((u->direction & 1) == 0) {
 
  483   for (; v->
Next() != NULL; v = v->
Next()) u = v;
 
  493 static void RoadVehSetRandomDirection(
RoadVehicle *v)
 
  495   static const DirDiff delta[] = {
 
  504   } 
while ((v = v->
Next()) != NULL);
 
  518     if ((v->
tick_counter & 7) == 0) RoadVehSetRandomDirection(v);
 
  520     bool ret = v->
Next() != NULL;
 
  561   uint pass = v->
Crash();
 
  564   Game::NewEvent(
new ScriptEventVehicleCrashed(v->
index, v->
tile, ScriptEventVehicleCrashed::CRASH_RV_LEVEL_CROSSING));
 
  569       STR_NEWS_ROAD_VEHICLE_CRASH_DRIVER : STR_NEWS_ROAD_VEHICLE_CRASH,
 
  574   ModifyStationRatingAround(v->
tile, v->
owner, -160, 22);
 
  610 static void StartRoadVehSound(
const RoadVehicle *v)
 
  614     if (s == SND_19_BUS_START_PULL_AWAY && (v->
tick_counter & 3) == 0) {
 
  615       s = SND_1A_BUS_START_PULL_AWAY_WITH_HORN;
 
  617     SndPlayVehicleFx(s, v);
 
  632   static const int8 dist_x[] = { -4, -8, -4, -1, 4, 8, 4, 1 };
 
  633   static const int8 dist_y[] = { -4, -1, 4, 8, 4, 1, -4, -8 };
 
  637   short x_diff = v->
x_pos - rvf->x;
 
  638   short y_diff = v->
y_pos - rvf->y;
 
  649     uint diff = 
abs(x_diff) + 
abs(y_diff);
 
  651     if (diff < rvf->best_diff || (diff == rvf->best_diff && v->
index < rvf->best->
index)) {
 
  653       rvf->best_diff = diff;
 
  665   if (front->reverse_ctr != 0) 
return NULL;
 
  671   rvf.best_diff = UINT_MAX;
 
  684   if (rvf.best_diff == UINT_MAX) {
 
  685     front->blocked_ctr = 0;
 
  689   if (update_blocked_ctr && ++front->blocked_ctr > 1480) 
return NULL;
 
  703     if (!(st->had_vehicle_of_type & 
HVOT_BUS)) {
 
  704       st->had_vehicle_of_type |= 
HVOT_BUS;
 
  707         v->roadtype == 
ROADTYPE_ROAD ? STR_NEWS_FIRST_BUS_ARRIVAL : STR_NEWS_FIRST_PASSENGER_TRAM_ARRIVAL,
 
  717     if (!(st->had_vehicle_of_type & 
HVOT_TRUCK)) {
 
  721         v->roadtype == 
ROADTYPE_ROAD ? STR_NEWS_FIRST_TRUCK_ARRIVAL : STR_NEWS_FIRST_CARGO_TRAM_ARRIVAL,
 
  742     default: NOT_REACHED();
 
  753   static const Direction _roadveh_new_dir[] = {
 
  759   x = x - v->
x_pos + 1;
 
  760   y = y - v->
y_pos + 1;
 
  762   if ((uint)x > 2 || (uint)y > 2) 
return v->
direction;
 
  763   return _roadveh_new_dir[y * 4 + x];
 
  768   Direction new_dir = RoadVehGetNewDirection(v, x, y);
 
  772   if (new_dir == old_dir) 
return old_dir;
 
  784 static Vehicle *EnumFindVehBlockingOvertake(
Vehicle *v, 
void *data)
 
  788   return (v->
type == 
VEH_ROAD && v->
First() == v && v != od->u && v != od->v) ? v : NULL;
 
  863 static void RoadZPosAffectSpeed(
RoadVehicle *v, 
int old_z)
 
  867   if (old_z < v->z_pos) {
 
  871     if (spd <= v->vcache.cached_max_speed) v->
cur_speed = spd;
 
  875 static int PickRandomBit(uint bits)
 
  880   for (i = 0; !(bits & 1) || (
int)--num >= 0; bits >>= 1, i++) {}
 
  894 #define return_track(x) { best_track = (Trackdir)x; goto found_best_track; } 
  898   bool path_found = 
true;
 
  938   trackdirs &= _road_enter_dir_to_reachable_trackdirs[enterdir];
 
  941     return_track(_road_reverse_table[enterdir]);
 
  944   if (v->reverse_ctr != 0) {
 
  951       reverse = ((rb & straight) == straight) ||
 
  956       if (v->
tile != tile) {
 
  957         return_track(_road_reverse_table[enterdir]);
 
  965     return_track(PickRandomBit(trackdirs));
 
  977     default: NOT_REACHED();
 
  994 static bool RoadVehLeaveDepot(
RoadVehicle *v, 
bool first)
 
 1004   Trackdir tdir = _roadveh_depot_exit_trackdir[dir];
 
 1017     if (RoadVehFindCloseTo(v, x, y, v->
direction, 
false) != NULL) 
return true;
 
 1021     StartRoadVehSound(v);
 
 1029   v->frame = RVC_DEPOT_START_FRAME;
 
 1043   if (prev->
tile == v->
tile && !already_reversed) {
 
 1046     return _road_reverse_table[entry_dir];
 
 1049   byte prev_state = prev->
state;
 
 1064     if (already_reversed && prev->
tile != tile) {
 
 1094   static const RoadBits required_roadbits[] = {
 
 1098   RoadBits required = required_roadbits[dir & 0x07];
 
 1189       dir = FollowPreviousRoadVehicle(v, prev, tile, (
DiagDirection)(rd.x & 3), 
false);
 
 1199     uint start_frame = RVC_DEFAULT_START_FRAME;
 
 1210           default: NOT_REACHED();
 
 1242           start_frame = RVC_TURN_AROUND_START_FRAME_SHORT_TRAM;
 
 1262     Direction new_dir = RoadVehGetSlidingDirection(v, x, y);
 
 1264       Vehicle *u = RoadVehFindCloseTo(v, x, y, new_dir);
 
 1278       dir = _road_reverse_table[rd.x & 3];
 
 1310       v->
state = (byte)dir;
 
 1311       v->frame = start_frame;
 
 1327     uint turn_around_start_frame = RVC_TURN_AROUND_START_FRAME;
 
 1339       turn_around_start_frame = RVC_START_FRAME_AFTER_LONG_TRAM;
 
 1340       switch (rd.x & 0x3) {
 
 1341         default: NOT_REACHED();
 
 1352         dir = FollowPreviousRoadVehicle(v, prev, v->
tile, (
DiagDirection)(rd.x & 3), 
true);
 
 1366     Direction new_dir = RoadVehGetSlidingDirection(v, x, y);
 
 1367     if (v->
IsFrontEngine() && RoadVehFindCloseTo(v, x, y, new_dir) != NULL) 
return false;
 
 1376     v->frame = turn_around_start_frame;
 
 1395       RoadVehLeaveDepot(v->
Next(), 
false);
 
 1400   int x = (v->
x_pos & ~15) + (rd.x & 15);
 
 1401   int y = (v->
y_pos & ~15) + (rd.y & 15);
 
 1403   Direction new_dir = RoadVehGetSlidingDirection(v, x, y);
 
 1408     RoadVehicle *u = RoadVehFindCloseTo(v, x, y, new_dir);
 
 1413       if (v->
overtaking == 0) RoadVehCheckOvertake(v, u);
 
 1431   if (new_dir != old_dir) {
 
 1454       v->frame == RVC_DRIVE_THROUGH_STOP_FRAME))) {
 
 1501     StartRoadVehSound(v);
 
 1531   if (v->reverse_ctr != 0) v->reverse_ctr--;
 
 1547   if (v->
IsInDepot() && RoadVehLeaveDepot(v, 
true)) 
return true;
 
 1555   bool blocked = 
false;
 
 1556   while (j >= adv_spd) {
 
 1561       if (!IndividualRoadVehicleController(u, prev)) {
 
 1572     if (j >= adv_spd && RoadVehCheckTrainCrash(v)) 
break;
 
 1578     if ((u->vehstatus & 
VS_HIDDEN) != 0) 
continue;
 
 1580     u->UpdateViewport(
false, 
false);
 
 1594   if (e->u.road.running_cost_class == INVALID_PRICE) 
return 0;
 
 1597   if (cost_factor == 0) 
return 0;
 
 1599   return GetPrice(e->u.road.running_cost_class, cost_factor, e->
GetGRF());
 
 1608     return RoadVehController(
this);
 
 1614 static void CheckIfRoadVehNeedsService(
RoadVehicle *v)
 
 1627     default: NOT_REACHED();
 
 1664   if (this->blocked_ctr == 0) CheckVehicleBreakdown(
this);
 
 1666   CheckIfRoadVehNeedsService(
this);