(svn r16037) -Feature: allow (per order) to let a train stop at the near end, middle or far end of a platform from the point of view of the driver of the train that enters the station.

This commit is contained in:
rubidium
2009-04-12 14:11:14 +00:00
parent e85e8ca4db
commit 5790293af6
14 changed files with 164 additions and 24 deletions

View File

@@ -354,6 +354,55 @@ enum AccelType {
AM_BRAKE
};
/**
* Get the stop location of (the center) of the front vehicle of a train at
* a platform of a station.
* @param station_id the ID of the station where we're stopping
* @param tile the tile where the vehicle currently is
* @param v the vehicle to get the stop location of
* @param station_ahead 'return' the amount of 1/16th tiles in front of the train
* @param station_length 'return' the station length in 1/16th tiles
* @return the location, calculated from the begin of the station to stop at.
*/
int GetTrainStopLocation(StationID station_id, TileIndex tile, const Vehicle *v, int *station_ahead, int *station_length)
{
const Station *st = GetStation(station_id);
*station_ahead = st->GetPlatformLength(tile, DirToDiagDir(v->direction)) * TILE_SIZE;
*station_length = st->GetPlatformLength(tile) * TILE_SIZE;
/* Default to the middle of the station for stations stops that are not in
* the order list like intermediate stations when non-stop is disabled */
OrderStopLocation osl = OSL_PLATFORM_MIDDLE;
if (v->u.rail.cached_total_length >= *station_length) {
/* The train is longer than the station, make it stop at the far end of the platform */
osl = OSL_PLATFORM_FAR_END;
} else if (v->current_order.IsType(OT_GOTO_STATION) && v->current_order.GetDestination() == station_id) {
osl = v->current_order.GetStopLocation();
}
/* The stop location of the FRONT! of the train */
int stop;
switch (osl) {
default: NOT_REACHED();
case OSL_PLATFORM_NEAR_END:
stop = v->u.rail.cached_total_length;
break;
case OSL_PLATFORM_MIDDLE:
stop = *station_length - (*station_length - v->u.rail.cached_total_length) / 2;
break;
case OSL_PLATFORM_FAR_END:
stop = *station_length;
break;
}
/* Substract half the front vehicle length of the train so we get the real
* stop location of the train. */
return stop - (v->u.rail.cached_veh_length + 1) / 2;
}
/** new acceleration*/
static int GetTrainAcceleration(Vehicle *v, bool mode)
{
@@ -416,17 +465,23 @@ static int GetTrainAcceleration(Vehicle *v, bool mode)
}
if (IsTileType(v->tile, MP_STATION) && IsFrontEngine(v)) {
if (v->current_order.ShouldStopAtStation(v, GetStationIndex(v->tile))) {
int station_length = GetStationByTile(v->tile)->GetPlatformLength(v->tile, DirToDiagDir(v->direction));
StationID sid = GetStationIndex(v->tile);
if (v->current_order.ShouldStopAtStation(v, sid)) {
int station_ahead;
int station_length;
int stop_at = GetTrainStopLocation(sid, v->tile, v, &station_ahead, &station_length);
/* The distance to go is whatever is still ahead of the train minus the
* distance from the train's stop location to the end of the platform */
int distance_to_go = station_ahead / TILE_SIZE - (station_length - stop_at) / TILE_SIZE;
int st_max_speed = 120;
int delta_v = v->cur_speed / (station_length + 1);
int delta_v = v->cur_speed / (distance_to_go + 1);
if (v->max_speed > (v->cur_speed - delta_v)) {
st_max_speed = v->cur_speed - (delta_v / 10);
}
st_max_speed = max(st_max_speed, 25 * station_length);
st_max_speed = max(st_max_speed, 25 * distance_to_go);
max_speed = min(max_speed, st_max_speed);
}
}
@@ -3781,6 +3836,11 @@ static void TrainController(Vehicle *v, Vehicle *nomove)
/* Always try to extend the reservation when entering a tile. */
CheckNextTrainTile(v);
}
if (HasBit(r, VETS_ENTERED_STATION)) {
/* The new position is the location where we want to stop */
TrainEnterStation(v, r >> VETS_STATION_ID_OFFSET);
}
}
} else {
/* In a tunnel or on a bridge