File diff r13848:aeebc2bae05b → r13849:0178a6ac1660
src/roadveh_cmd.cpp
Show inline comments
 
@@ -420,103 +420,97 @@ CommandCost CmdTurnRoadVeh(TileIndex til
 
			v->state == RVSB_WORMHOLE ||
 
			v->IsInDepot() ||
 
			v->cur_speed < 5) {
 
		return CMD_ERROR;
 
	}
 

	
 
	if (IsNormalRoadTile(v->tile) && GetDisallowedRoadDirections(v->tile) != DRD_NONE) return CMD_ERROR;
 

	
 
	if (IsTileType(v->tile, MP_TUNNELBRIDGE) && DirToDiagDir(v->direction) == GetTunnelBridgeDirection(v->tile)) return CMD_ERROR;
 

	
 
	if (flags & DC_EXEC) v->reverse_ctr = 180;
 

	
 
	return CommandCost();
 
}
 

	
 

	
 
void RoadVehicle::MarkDirty()
 
{
 
	for (Vehicle *v = this; v != NULL; v = v->Next()) {
 
		v->UpdateViewport(false, false);
 
	}
 
}
 

	
 
void RoadVehicle::UpdateDeltaXY(Direction direction)
 
{
 
#define MKIT(a, b, c, d) ((a & 0xFF) << 24) | ((b & 0xFF) << 16) | ((c & 0xFF) << 8) | ((d & 0xFF) << 0)
 
	static const uint32 _delta_xy_table[8] = {
 
		MKIT(3, 3, -1, -1),
 
		MKIT(3, 7, -1, -3),
 
		MKIT(3, 3, -1, -1),
 
		MKIT(7, 3, -3, -1),
 
		MKIT(3, 3, -1, -1),
 
		MKIT(3, 7, -1, -3),
 
		MKIT(3, 3, -1, -1),
 
		MKIT(7, 3, -3, -1),
 
	};
 
#undef MKIT
 

	
 
	uint32 x = _delta_xy_table[direction];
 
	this->x_offs        = GB(x,  0, 8);
 
	this->y_offs        = GB(x,  8, 8);
 
	this->x_extent      = GB(x, 16, 8);
 
	this->y_extent      = GB(x, 24, 8);
 
	this->z_extent      = 6;
 
}
 

	
 
static void ClearCrashedStation(RoadVehicle *v)
 
{
 
	RoadStop *rs = RoadStop::GetByTile(v->tile, GetRoadStopType(v->tile));
 

	
 
	/* Mark the station entrance as not busy */
 
	rs->SetEntranceBusy(false);
 

	
 
	/* Free the parking bay */
 
	rs->FreeBay(HasBit(v->state, RVS_USING_SECOND_BAY));
 
	RoadStop::GetByTile(v->tile, GetRoadStopType(v->tile))->Leave(v);
 
}
 

	
 
static void DeleteLastRoadVeh(RoadVehicle *v)
 
{
 
	Vehicle *u = v;
 
	for (; v->Next() != NULL; v = v->Next()) u = v;
 
	u->SetNext(NULL);
 

	
 
	if (IsTileType(v->tile, MP_STATION)) ClearCrashedStation(v);
 

	
 
	delete v;
 
}
 

	
 
static byte SetRoadVehPosition(RoadVehicle *v, int x, int y, bool turned)
 
{
 
	byte new_z, old_z;
 

	
 
	/* need this hint so it returns the right z coordinate on bridges. */
 
	v->x_pos = x;
 
	v->y_pos = y;
 
	new_z = GetSlopeZ(x, y);
 

	
 
	old_z = v->z_pos;
 
	v->z_pos = new_z;
 

	
 
	v->UpdateViewport(true, turned);
 
	return old_z;
 
}
 

	
 
static void RoadVehSetRandomDirection(RoadVehicle *v)
 
{
 
	static const DirDiff delta[] = {
 
		DIRDIFF_45LEFT, DIRDIFF_SAME, DIRDIFF_SAME, DIRDIFF_45RIGHT
 
	};
 

	
 
	do {
 
		uint32 r = Random();
 

	
 
		v->direction = ChangeDir(v->direction, delta[r & 3]);
 
		SetRoadVehPosition(v, v->x_pos, v->y_pos, true);
 
	} while ((v = v->Next()) != NULL);
 
}
 

	
 
static bool RoadVehIsCrashed(RoadVehicle *v)
 
{
 
	v->crashed_ctr++;
 
	if (v->crashed_ctr == 2) {
 
		CreateEffectVehicleRel(v, 4, 4, 8, EV_EXPLOSION_LARGE);
 
@@ -1272,107 +1266,97 @@ again:
 
					tile = v->tile;
 
					start_frame = RVC_TURN_AROUND_START_FRAME_SHORT_TRAM;
 
				} else {
 
					/* The company can build on the next tile, so wait till (s)he does. */
 
					v->cur_speed = 0;
 
					return false;
 
				}
 
			} else if (IsNormalRoadTile(v->tile) && GetDisallowedRoadDirections(v->tile) != DRD_NONE) {
 
				v->cur_speed = 0;
 
				return false;
 
			} else {
 
				tile = v->tile;
 
			}
 
		}
 

	
 
		/* Get position data for first frame on the new tile */
 
		const RoadDriveEntry *rdp = _road_drive_data[v->roadtype][(dir + (_settings_game.vehicle.road_side << RVS_DRIVE_SIDE)) ^ v->overtaking];
 

	
 
		int x = TileX(tile) * TILE_SIZE + rdp[start_frame].x;
 
		int y = TileY(tile) * TILE_SIZE + rdp[start_frame].y;
 

	
 
		Direction new_dir = RoadVehGetSlidingDirection(v, x, y);
 
		if (v->IsRoadVehFront()) {
 
			Vehicle *u = RoadVehFindCloseTo(v, x, y, new_dir);
 
			if (u != NULL) {
 
				v->cur_speed = u->First()->cur_speed;
 
				return false;
 
			}
 
		}
 

	
 
		uint32 r = VehicleEnterTile(v, tile, x, y);
 
		if (HasBit(r, VETS_CANNOT_ENTER)) {
 
			if (!IsTileType(tile, MP_TUNNELBRIDGE)) {
 
				v->cur_speed = 0;
 
				return false;
 
			}
 
			/* Try an about turn to re-enter the previous tile */
 
			dir = _road_reverse_table[rd.x & 3];
 
			goto again;
 
		}
 

	
 
		if (IsInsideMM(v->state, RVSB_IN_ROAD_STOP, RVSB_IN_DT_ROAD_STOP_END) && IsTileType(v->tile, MP_STATION)) {
 
			if (IsReversingRoadTrackdir(dir) && IsInsideMM(v->state, RVSB_IN_ROAD_STOP, RVSB_IN_ROAD_STOP_END)) {
 
				/* New direction is trying to turn vehicle around.
 
				 * We can't turn at the exit of a road stop so wait.*/
 
				v->cur_speed = 0;
 
				return false;
 
			}
 
			if (IsRoadStop(v->tile)) {
 
				RoadStop *rs = RoadStop::GetByTile(v->tile, GetRoadStopType(v->tile));
 

	
 
				/* Vehicle is leaving a road stop tile, mark bay as free
 
				 * For drive-through stops, only do it if the vehicle stopped here */
 
				if (IsStandardRoadStopTile(v->tile) || HasBit(v->state, RVS_IS_STOPPING)) {
 
					rs->FreeBay(HasBit(v->state, RVS_USING_SECOND_BAY));
 
					ClrBit(v->state, RVS_IS_STOPPING);
 
				}
 
				if (IsStandardRoadStopTile(v->tile)) rs->SetEntranceBusy(false);
 
			}
 
			if (IsRoadStop(v->tile)) RoadStop::GetByTile(v->tile, GetRoadStopType(v->tile))->Leave(v);
 
		}
 

	
 
		if (!HasBit(r, VETS_ENTERED_WORMHOLE)) {
 
			v->tile = tile;
 
			v->state = (byte)dir;
 
			v->frame = start_frame;
 
		}
 
		if (new_dir != v->direction) {
 
			v->direction = new_dir;
 
			v->cur_speed -= v->cur_speed >> 2;
 
		}
 

	
 
		RoadZPosAffectSpeed(v, SetRoadVehPosition(v, x, y, true));
 
		return true;
 
	}
 

	
 
	if (rd.x & RDE_TURNED) {
 
		/* Vehicle has finished turning around, it will now head back onto the same tile */
 
		Trackdir dir;
 
		uint turn_around_start_frame = RVC_TURN_AROUND_START_FRAME;
 

	
 
		RoadBits tram;
 
		if (v->roadtype == ROADTYPE_TRAM && !IsRoadDepotTile(v->tile) && CountBits(tram = GetAnyRoadBits(v->tile, ROADTYPE_TRAM, true)) == 1) {
 
			/*
 
			 * The tram is turning around with one tram 'roadbit'. This means that
 
			 * it is using the 'big' corner 'drive data'. However, to support the
 
			 * trams to take a small corner, there is a 'turned' marker in the middle
 
			 * of the turning 'drive data'. When the tram took the long corner, we
 
			 * will still use the 'big' corner drive data, but we advance it one
 
			 * frame. We furthermore set the driving direction so the turning is
 
			 * going to be properly shown.
 
			 */
 
			turn_around_start_frame = RVC_START_FRAME_AFTER_LONG_TRAM;
 
			switch (rd.x & 0x3) {
 
				default: NOT_REACHED();
 
				case DIAGDIR_NW: dir = TRACKDIR_RVREV_SE; break;
 
				case DIAGDIR_NE: dir = TRACKDIR_RVREV_SW; break;
 
				case DIAGDIR_SE: dir = TRACKDIR_RVREV_NW; break;
 
				case DIAGDIR_SW: dir = TRACKDIR_RVREV_NE; break;
 
			}
 
		} else {
 
			if (v->IsRoadVehFront()) {
 
				/* If this is the front engine, look for the right path. */
 
				dir = RoadFindPathToDest(v, v->tile, (DiagDirection)(rd.x & 3));
 
			} else {
 
				dir = FollowPreviousRoadVehicle(v, prev, v->tile, (DiagDirection)(rd.x & 3), true);
 
			}
 
		}