Changeset - r5856:e64c21408d74
[Not reviewed]
master
0 3 0
tron - 18 years ago 2007-01-27 16:45:16
tron@openttd.org
(svn r8430) -Fix

Replace the rather obscure control flow for handling aircraft/ship/train orders by something remotly comprehensible (see r3584)
3 files changed with 73 insertions and 62 deletions:
0 comments (0 inline, 0 general)
src/aircraft_cmd.cpp
Show inline comments
 
@@ -1164,217 +1164,221 @@ static void HandleBrokenAircraft(Vehicle
 

	
 

	
 
static void HandleAircraftSmoke(Vehicle *v)
 
{
 
	static const struct {
 
		int8 x;
 
		int8 y;
 
	} smoke_pos[] = {
 
		{  5,  5 },
 
		{  6,  0 },
 
		{  5, -5 },
 
		{  0, -6 },
 
		{ -5, -5 },
 
		{ -6,  0 },
 
		{ -5,  5 },
 
		{  0,  6 }
 
	};
 

	
 
	if (!(v->vehstatus & VS_AIRCRAFT_BROKEN)) return;
 

	
 
	if (v->cur_speed < 10) {
 
		v->vehstatus &= ~VS_AIRCRAFT_BROKEN;
 
		v->breakdown_ctr = 0;
 
		return;
 
	}
 

	
 
	if ((v->tick_counter & 0x1F) == 0) {
 
		CreateEffectVehicleRel(v,
 
			smoke_pos[v->direction].x,
 
			smoke_pos[v->direction].y,
 
			2,
 
			EV_SMOKE
 
		);
 
	}
 
}
 

	
 
static void ProcessAircraftOrder(Vehicle *v)
 
{
 
	const Order *order;
 

	
 
	switch (v->current_order.type) {
 
		case OT_GOTO_DEPOT:
 
			if (!(v->current_order.flags & OF_PART_OF_ORDERS)) return;
 
			if (v->current_order.flags & OF_SERVICE_IF_NEEDED &&
 
					!VehicleNeedsService(v)) {
 
				v->cur_order_index++;
 
			}
 
			break;
 

	
 
		case OT_LOADING: return;
 

	
 
		default: break;
 
	}
 

	
 
	if (v->cur_order_index >= v->num_orders) v->cur_order_index = 0;
 

	
 
	order = GetVehicleOrder(v, v->cur_order_index);
 

	
 
	if (order == NULL) {
 
		v->current_order.type = OT_NOTHING;
 
		v->current_order.flags = 0;
 
		return;
 
	}
 

	
 
	if (order->type == OT_DUMMY && !CheckForValidOrders(v)) CrashAirplane(v);
 

	
 
	if (order->type  == v->current_order.type  &&
 
			order->flags == v->current_order.flags &&
 
			order->dest  == v->current_order.dest)
 
		return;
 

	
 
	v->current_order = *order;
 

	
 
	// orders are changed in flight, ensure going to the right station
 
	if (order->type == OT_GOTO_STATION && v->u.air.state == FLYING) {
 
		AircraftNextAirportPos_and_Order(v);
 
		v->u.air.targetairport = order->dest;
 
	}
 

	
 
	InvalidateVehicleOrder(v);
 

	
 
	InvalidateWindowClasses(WC_AIRCRAFT_LIST);
 
}
 

	
 
/** Mark all views dirty for an aircraft.
 
 * @param v vehicle to be redrawn.
 
 */
 
static void MarkAircraftDirty(Vehicle *v)
 
{
 
		v->cur_image = GetAircraftImage(v, v->direction);
 
		if (v->subtype == AIR_HELICOPTER) v->next->next->cur_image = GetRotorImage(v);
 
		MarkAllViewportsDirty(v->left_coord, v->top_coord, v->right_coord + 1, v->bottom_coord + 1);
 
}
 

	
 
static void HandleAircraftLoading(Vehicle *v, int mode)
 
{
 
	if (v->current_order.type == OT_NOTHING) return;
 

	
 
	if (v->current_order.type != OT_DUMMY) {
 
		if (v->current_order.type != OT_LOADING) return;
 
		if (mode != 0) return;
 
		if (--v->load_unload_time_rem != 0) return;
 
	switch (v->current_order.type) {
 
		case OT_LOADING:
 
			if (mode != 0) return;
 
			if (--v->load_unload_time_rem != 0) return;
 

	
 
		if (CanFillVehicle(v) && (v->current_order.flags & OF_FULL_LOAD ||
 
				(_patches.gradual_loading && !HASBIT(v->load_status, LS_LOADING_FINISHED)))) {
 
			SET_EXPENSES_TYPE(EXPENSES_AIRCRAFT_INC);
 
			if (LoadUnloadVehicle(v, false)) {
 
				InvalidateWindow(WC_AIRCRAFT_LIST, v->owner);
 
				MarkAircraftDirty(v);
 
			if (CanFillVehicle(v) && (
 
						v->current_order.flags & OF_FULL_LOAD ||
 
						(_patches.gradual_loading && !HASBIT(v->load_status, LS_LOADING_FINISHED))
 
					)) {
 
				SET_EXPENSES_TYPE(EXPENSES_AIRCRAFT_INC);
 
				if (LoadUnloadVehicle(v, false)) {
 
					InvalidateWindow(WC_AIRCRAFT_LIST, v->owner);
 
					MarkAircraftDirty(v);
 
				}
 
				return;
 
			}
 
			return;
 
		}
 

	
 
		{
 
			Order b = v->current_order;
 
			v->current_order.type = OT_NOTHING;
 
			v->current_order.flags = 0;
 
			MarkAircraftDirty(v);
 
			if (!(b.flags & OF_NON_STOP)) return;
 
		}
 
			break;
 

	
 
		case OT_DUMMY: break;
 

	
 
		default: return;
 
	}
 

	
 
	v->cur_order_index++;
 
	InvalidateVehicleOrder(v);
 
}
 

	
 
static void CrashAirplane(Vehicle *v)
 
{
 
	uint16 amt;
 
	Station *st;
 
	StringID newsitem;
 

	
 
	v->vehstatus |= VS_CRASHED;
 
	v->u.air.crashed_counter = 0;
 

	
 
	CreateEffectVehicleRel(v, 4, 4, 8, EV_EXPLOSION_LARGE);
 

	
 
	InvalidateWindow(WC_VEHICLE_VIEW, v->index);
 

	
 
	amt = 2;
 
	if (v->cargo_type == CT_PASSENGERS) amt += v->cargo_count;
 
	SetDParam(0, amt);
 

	
 
	v->cargo_count = 0;
 
	v->next->cargo_count = 0,
 
	st = GetStation(v->u.air.targetairport);
 
	if (st->airport_tile == 0) {
 
		newsitem = STR_PLANE_CRASH_OUT_OF_FUEL;
 
	} else {
 
		SetDParam(1, st->index);
 
		newsitem = STR_A034_PLANE_CRASH_DIE_IN_FIREBALL;
 
	}
 

	
 
	SetDParam(1, st->index);
 
	AddNewsItem(newsitem,
 
		NEWS_FLAGS(NM_THIN, NF_VIEWPORT|NF_VEHICLE, NT_ACCIDENT, 0),
 
		v->index,
 
		0);
 

	
 
	SndPlayVehicleFx(SND_12_EXPLOSION, v);
 
}
 

	
 
static void MaybeCrashAirplane(Vehicle *v)
 
{
 
	Station *st;
 
	uint16 prob;
 
	uint i;
 

	
 
	st = GetStation(v->u.air.targetairport);
 

	
 
	//FIXME -- MaybeCrashAirplane -> increase crashing chances of very modern airplanes on smaller than AT_METROPOLITAN airports
 
	prob = 0x10000 / 1500;
 
	if (((st->airport_type == AT_SMALL) || (st->airport_type == AT_COMMUTER)) && (AircraftVehInfo(v->engine_type)->subtype & AIR_FAST) && !_cheats.no_jetcrash.value) {
 
		prob = 0x10000 / 20;
 
	}
 

	
 
	if (GB(Random(), 0, 16) > prob) return;
 

	
 
	// Crash the airplane. Remove all goods stored at the station.
 
	for (i = 0; i != NUM_CARGO; i++) {
 
		st->goods[i].rating = 1;
 
		SB(st->goods[i].waiting_acceptance, 0, 12, 0);
 
	}
 

	
 
	CrashAirplane(v);
 
}
 

	
 
// we've landed and just arrived at a terminal
 
static void AircraftEntersTerminal(Vehicle *v)
 
{
 
	Station *st;
 
	Order old_order;
 

	
 
	if (v->current_order.type == OT_GOTO_DEPOT) return;
 

	
 
	st = GetStation(v->u.air.targetairport);
 
	v->last_station_visited = v->u.air.targetairport;
 

	
 
	/* Check if station was ever visited before */
 
	if (!(st->had_vehicle_of_type & HVOT_AIRCRAFT)) {
 
		uint32 flags;
 

	
 
		st->had_vehicle_of_type |= HVOT_AIRCRAFT;
 
		SetDParam(0, st->index);
 
		// show newsitem of celebrating citizens
 
		flags = (v->owner == _local_player) ? NEWS_FLAGS(NM_THIN, NF_VIEWPORT|NF_VEHICLE, NT_ARRIVAL_PLAYER, 0) : NEWS_FLAGS(NM_THIN, NF_VIEWPORT|NF_VEHICLE, NT_ARRIVAL_OTHER, 0);
 
		AddNewsItem(
 
			STR_A033_CITIZENS_CELEBRATE_FIRST,
 
			flags,
 
			v->index,
 
			0);
 
	}
 

	
 
	old_order = v->current_order;
 
	v->BeginLoading();
 
	v->current_order.flags = 0;
 

	
 
	if (old_order.type == OT_GOTO_STATION &&
src/ship_cmd.cpp
Show inline comments
 
@@ -180,214 +180,217 @@ static void HandleBrokenShip(Vehicle *v)
 
		InvalidateWindow(WC_VEHICLE_VIEW, v->index);
 
		InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
 

	
 
		if (!PlayVehicleSound(v, VSE_BREAKDOWN)) {
 
			SndPlayVehicleFx((_opt.landscape != LT_CANDY) ?
 
				SND_10_TRAIN_BREAKDOWN : SND_3A_COMEDY_BREAKDOWN_2, v);
 
		}
 

	
 
		if (!(v->vehstatus & VS_HIDDEN)) {
 
			Vehicle *u = CreateEffectVehicleRel(v, 4, 4, 5, EV_BREAKDOWN_SMOKE);
 
			if (u != NULL) u->u.special.unk0 = v->breakdown_delay * 2;
 
		}
 
	}
 

	
 
	if (!(v->tick_counter & 1)) {
 
		if (!--v->breakdown_delay) {
 
			v->breakdown_ctr = 0;
 
			InvalidateWindow(WC_VEHICLE_VIEW, v->index);
 
		}
 
	}
 
}
 

	
 
static void MarkShipDirty(Vehicle *v)
 
{
 
	v->cur_image = GetShipImage(v, v->direction);
 
	MarkAllViewportsDirty(v->left_coord, v->top_coord, v->right_coord + 1, v->bottom_coord + 1);
 
}
 

	
 
static void PlayShipSound(Vehicle *v)
 
{
 
	if (!PlayVehicleSound(v, VSE_START)) {
 
		SndPlayVehicleFx(ShipVehInfo(v->engine_type)->sfx, v);
 
	}
 
}
 

	
 
static void ProcessShipOrder(Vehicle *v)
 
{
 
	const Order *order;
 

	
 
	switch (v->current_order.type) {
 
		case OT_GOTO_DEPOT:
 
			if (!(v->current_order.flags & OF_PART_OF_ORDERS)) return;
 
			if (v->current_order.flags & OF_SERVICE_IF_NEEDED &&
 
					!VehicleNeedsService(v)) {
 
				v->cur_order_index++;
 
			}
 
			break;
 

	
 
		case OT_LOADING:
 
		case OT_LEAVESTATION:
 
			return;
 

	
 
		default: break;
 
	}
 

	
 
	if (v->cur_order_index >= v->num_orders) v->cur_order_index = 0;
 

	
 
	order = GetVehicleOrder(v, v->cur_order_index);
 

	
 
	if (order == NULL) {
 
		v->current_order.type  = OT_NOTHING;
 
		v->current_order.flags = 0;
 
		v->dest_tile = 0;
 
		return;
 
	}
 

	
 
	if (order->type  == v->current_order.type &&
 
			order->flags == v->current_order.flags &&
 
			order->dest  == v->current_order.dest)
 
		return;
 

	
 
	v->current_order = *order;
 

	
 
	if (order->type == OT_GOTO_STATION) {
 
		const Station *st;
 

	
 
		if (order->dest == v->last_station_visited)
 
			v->last_station_visited = INVALID_STATION;
 

	
 
		st = GetStation(order->dest);
 
		if (st->dock_tile != 0) {
 
			v->dest_tile = TILE_ADD(st->dock_tile, ToTileIndexDiff(GetDockOffset(st->dock_tile)));
 
		}
 
	} else if (order->type == OT_GOTO_DEPOT) {
 
		v->dest_tile = GetDepot(order->dest)->xy;
 
	} else {
 
		v->dest_tile = 0;
 
	}
 

	
 
	InvalidateVehicleOrder(v);
 

	
 
	InvalidateWindowClasses(WC_SHIPS_LIST);
 
}
 

	
 
static void HandleShipLoading(Vehicle *v)
 
{
 
	if (v->current_order.type == OT_NOTHING) return;
 

	
 
	if (v->current_order.type != OT_DUMMY) {
 
		if (v->current_order.type != OT_LOADING) return;
 
		if (--v->load_unload_time_rem) return;
 
	switch (v->current_order.type) {
 
		case OT_LOADING:
 
			if (--v->load_unload_time_rem) return;
 

	
 
		if (CanFillVehicle(v) && (v->current_order.flags & OF_FULL_LOAD ||
 
				(_patches.gradual_loading && !HASBIT(v->load_status, LS_LOADING_FINISHED)))) {
 
			SET_EXPENSES_TYPE(EXPENSES_SHIP_INC);
 
			if (LoadUnloadVehicle(v, false)) {
 
				InvalidateWindow(WC_SHIPS_LIST, v->owner);
 
				MarkShipDirty(v);
 
			if (CanFillVehicle(v) && (
 
						v->current_order.flags & OF_FULL_LOAD ||
 
						(_patches.gradual_loading && !HASBIT(v->load_status, LS_LOADING_FINISHED))
 
					)) {
 
				SET_EXPENSES_TYPE(EXPENSES_SHIP_INC);
 
				if (LoadUnloadVehicle(v, false)) {
 
					InvalidateWindow(WC_SHIPS_LIST, v->owner);
 
					MarkShipDirty(v);
 
				}
 
				return;
 
			}
 
			return;
 
		}
 
		PlayShipSound(v);
 
			PlayShipSound(v);
 

	
 
		{
 
			Order b = v->current_order;
 
			v->LeaveStation();
 
			if (!(b.flags & OF_NON_STOP)) return;
 
		}
 
			break;
 

	
 
		case OT_DUMMY: break;
 

	
 
		default: return;
 
	}
 

	
 
	v->cur_order_index++;
 
	InvalidateVehicleOrder(v);
 
}
 

	
 
static void UpdateShipDeltaXY(Vehicle *v, int dir)
 
{
 
#define MKIT(d,c,b,a) ((a&0xFF)<<24) | ((b&0xFF)<<16) | ((c&0xFF)<<8) | ((d&0xFF)<<0)
 
	static const uint32 _delta_xy_table[8] = {
 
		MKIT( -3,  -3,  6,  6),
 
		MKIT(-16,  -3, 32,  6),
 
		MKIT( -3,  -3,  6,  6),
 
		MKIT( -3, -16,  6, 32),
 
		MKIT( -3,  -3,  6,  6),
 
		MKIT(-16,  -3, 32,  6),
 
		MKIT( -3,  -3,  6,  6),
 
		MKIT( -3, -16,  6, 32),
 
	};
 
#undef MKIT
 
	uint32 x = _delta_xy_table[dir];
 
	v->x_offs        = GB(x,  0, 8);
 
	v->y_offs        = GB(x,  8, 8);
 
	v->sprite_width  = GB(x, 16, 8);
 
	v->sprite_height = GB(x, 24, 8);
 
}
 

	
 
void RecalcShipStuff(Vehicle *v)
 
{
 
	UpdateShipDeltaXY(v, v->direction);
 
	v->cur_image = GetShipImage(v, v->direction);
 
	MarkShipDirty(v);
 
	InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
 
}
 

	
 
static const TileIndexDiffC _ship_leave_depot_offs[] = {
 
	{-1,  0},
 
	{ 0, -1}
 
};
 

	
 
static void CheckShipLeaveDepot(Vehicle *v)
 
{
 
	TileIndex tile;
 
	Axis axis;
 
	uint m;
 

	
 
	if (!IsShipInDepot(v)) return;
 

	
 
	tile = v->tile;
 
	axis = GetShipDepotAxis(tile);
 

	
 
	// Check first side
 
	if (_ship_sometracks[axis] & GetTileShipTrackStatus(TILE_ADD(tile, ToTileIndexDiff(_ship_leave_depot_offs[axis])))) {
 
		m = (axis == AXIS_X) ? 0x101 : 0x207;
 
	// Check second side
 
	} else if (_ship_sometracks[axis + 2] & GetTileShipTrackStatus(TILE_ADD(tile, -2 * ToTileIndexDiff(_ship_leave_depot_offs[axis])))) {
 
		m = (axis == AXIS_X) ? 0x105 : 0x203;
 
	} else {
 
		return;
 
	}
 
	v->direction    = (Direction)GB(m, 0, 8);
 
	v->u.ship.state = (TrackBits)GB(m, 8, 8);
 
	v->vehstatus &= ~VS_HIDDEN;
 

	
 
	v->cur_speed = 0;
 
	RecalcShipStuff(v);
 

	
 
	PlayShipSound(v);
 
	VehicleServiceInDepot(v);
 
	InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
 
	InvalidateWindowClasses(WC_SHIPS_LIST);
 
}
 

	
 
static bool ShipAccelerate(Vehicle *v)
 
{
 
	uint spd;
 
	byte t;
 

	
 
	spd = min(v->cur_speed + 1, v->max_speed);
 

	
 
	//updates statusbar only if speed have changed to save CPU time
 
	if (spd != v->cur_speed) {
 
		v->cur_speed = spd;
 
		if (_patches.vehicle_speed)
 
			InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR);
 
	}
 

	
 
	// Decrease somewhat when turning
 
	if (!(v->direction & 1)) spd = spd * 3 / 4;
 

	
 
	if (spd == 0) return false;
 
	if ((byte)++spd == 0) return true;
 

	
 
	v->progress = (t = v->progress) - (byte)spd;
 

	
 
	return (t < v->progress);
src/train_cmd.cpp
Show inline comments
 
@@ -2512,228 +2512,232 @@ bad:;
 
	return reverse_best != 0;
 
}
 

	
 
static bool ProcessTrainOrder(Vehicle *v)
 
{
 
	const Order *order;
 
	bool at_waypoint = false;
 

	
 
	switch (v->current_order.type) {
 
		case OT_GOTO_DEPOT:
 
			if (!(v->current_order.flags & OF_PART_OF_ORDERS)) return false;
 
			if ((v->current_order.flags & OF_SERVICE_IF_NEEDED) &&
 
					!VehicleNeedsService(v)) {
 
				v->cur_order_index++;
 
			}
 
			break;
 

	
 
		case OT_LOADING:
 
		case OT_LEAVESTATION:
 
			return false;
 

	
 
		default: break;
 
	}
 

	
 
	// check if we've reached the waypoint?
 
	if (v->current_order.type == OT_GOTO_WAYPOINT && v->tile == v->dest_tile) {
 
		v->cur_order_index++;
 
		at_waypoint = true;
 
	}
 

	
 
	// check if we've reached a non-stop station while TTDPatch nonstop is enabled..
 
	if (_patches.new_nonstop &&
 
			v->current_order.flags & OF_NON_STOP &&
 
			IsTileType(v->tile, MP_STATION) &&
 
			v->current_order.dest == GetStationIndex(v->tile)) {
 
		v->cur_order_index++;
 
	}
 

	
 
	// Get the current order
 
	if (v->cur_order_index >= v->num_orders) v->cur_order_index = 0;
 

	
 
	order = GetVehicleOrder(v, v->cur_order_index);
 

	
 
	// If no order, do nothing.
 
	if (order == NULL) {
 
		v->current_order.type = OT_NOTHING;
 
		v->current_order.flags = 0;
 
		v->dest_tile = 0;
 
		return false;
 
	}
 

	
 
	// If it is unchanged, keep it.
 
	if (order->type  == v->current_order.type &&
 
			order->flags == v->current_order.flags &&
 
			order->dest  == v->current_order.dest)
 
		return false;
 

	
 
	// Otherwise set it, and determine the destination tile.
 
	v->current_order = *order;
 

	
 
	v->dest_tile = 0;
 

	
 
	InvalidateVehicleOrder(v);
 

	
 
	switch (order->type) {
 
		case OT_GOTO_STATION:
 
			if (order->dest == v->last_station_visited)
 
				v->last_station_visited = INVALID_STATION;
 
			v->dest_tile = GetStation(order->dest)->xy;
 
			break;
 

	
 
		case OT_GOTO_DEPOT:
 
			v->dest_tile = GetDepot(order->dest)->xy;
 
			break;
 

	
 
		case OT_GOTO_WAYPOINT:
 
			v->dest_tile = GetWaypoint(order->dest)->xy;
 
			break;
 

	
 
		default:
 
			return false;
 
	}
 

	
 
	return !at_waypoint && CheckReverseTrain(v);
 
}
 

	
 
static void MarkTrainDirty(Vehicle *v)
 
{
 
	do {
 
		v->cur_image = GetTrainImage(v, v->direction);
 
		MarkAllViewportsDirty(v->left_coord, v->top_coord, v->right_coord + 1, v->bottom_coord + 1);
 
	} while ((v = v->next) != NULL);
 
}
 

	
 
static void HandleTrainLoading(Vehicle *v, bool mode)
 
{
 
	if (v->current_order.type == OT_NOTHING) return;
 

	
 
	if (v->current_order.type != OT_DUMMY) {
 
		if (v->current_order.type != OT_LOADING) return;
 
		if (mode) return;
 

	
 
		// don't mark the train as lost if we're loading on the final station.
 
		if (v->current_order.flags & OF_NON_STOP)
 
			v->u.rail.days_since_order_progr = 0;
 

	
 
		if (--v->load_unload_time_rem) return;
 

	
 
		if (CanFillVehicle(v) && (v->current_order.flags & OF_FULL_LOAD ||
 
				(_patches.gradual_loading && !HASBIT(v->load_status, LS_LOADING_FINISHED)))) {
 
			v->u.rail.days_since_order_progr = 0; /* Prevent a train lost message for full loading trains */
 
			SET_EXPENSES_TYPE(EXPENSES_TRAIN_INC);
 
			if (LoadUnloadVehicle(v, false)) {
 
				InvalidateWindow(WC_TRAINS_LIST, v->owner);
 
				MarkTrainDirty(v);
 

	
 
				// need to update acceleration and cached values since the goods on the train changed.
 
				TrainCargoChanged(v);
 
				UpdateTrainAcceleration(v);
 
	switch (v->current_order.type) {
 
		case OT_LOADING:
 
			if (mode) return;
 

	
 
			// don't mark the train as lost if we're loading on the final station.
 
			if (v->current_order.flags & OF_NON_STOP) {
 
				v->u.rail.days_since_order_progr = 0;
 
			}
 
			return;
 
		}
 

	
 
		TrainPlayLeaveStationSound(v);
 

	
 
		{
 

	
 
			if (--v->load_unload_time_rem) return;
 

	
 
			if (CanFillVehicle(v) && (
 
						v->current_order.flags & OF_FULL_LOAD ||
 
						(_patches.gradual_loading && !HASBIT(v->load_status, LS_LOADING_FINISHED))
 
					)) {
 
				v->u.rail.days_since_order_progr = 0; /* Prevent a train lost message for full loading trains */
 
				SET_EXPENSES_TYPE(EXPENSES_TRAIN_INC);
 
				if (LoadUnloadVehicle(v, false)) {
 
					InvalidateWindow(WC_TRAINS_LIST, v->owner);
 
					MarkTrainDirty(v);
 

	
 
					// need to update acceleration and cached values since the goods on the train changed.
 
					TrainCargoChanged(v);
 
					UpdateTrainAcceleration(v);
 
				}
 
				return;
 
			}
 

	
 
			TrainPlayLeaveStationSound(v);
 

	
 
			Order b = v->current_order;
 
			v->LeaveStation();
 

	
 
			// If this was not the final order, don't remove it from the list.
 
			if (!(b.flags & OF_NON_STOP)) return;
 
		}
 
			break;
 

	
 
		case OT_DUMMY: break;
 

	
 
		default: return;
 
	}
 

	
 
	v->u.rail.days_since_order_progr = 0;
 
	v->cur_order_index++;
 
	InvalidateVehicleOrder(v);
 
}
 

	
 
static int UpdateTrainSpeed(Vehicle *v)
 
{
 
	uint spd;
 
	uint accel;
 

	
 
	if (v->vehstatus & VS_STOPPED || HASBIT(v->u.rail.flags, VRF_REVERSING)) {
 
		if (_patches.realistic_acceleration) {
 
			accel = GetTrainAcceleration(v, AM_BRAKE) * 2;
 
		} else {
 
			accel = v->acceleration * -2;
 
		}
 
	} else {
 
		if (_patches.realistic_acceleration) {
 
			accel = GetTrainAcceleration(v, AM_ACCEL);
 
		} else {
 
			accel = v->acceleration;
 
		}
 
	}
 

	
 
	spd = v->subspeed + accel * 2;
 
	v->subspeed = (byte)spd;
 
	{
 
		int tempmax = v->max_speed;
 
		if (v->cur_speed > v->max_speed)
 
			tempmax = v->cur_speed - (v->cur_speed / 10) - 1;
 
		v->cur_speed = spd = clamp(v->cur_speed + ((int)spd >> 8), 0, tempmax);
 
	}
 

	
 
	if (!(v->direction & 1)) spd = spd * 3 >> 2;
 

	
 
	spd += v->progress;
 
	v->progress = (byte)spd;
 
	return (spd >> 8);
 
}
 

	
 
static void TrainEnterStation(Vehicle *v, StationID station)
 
{
 
	Station *st;
 
	uint32 flags;
 

	
 
	v->last_station_visited = station;
 

	
 
	/* check if a train ever visited this station before */
 
	st = GetStation(station);
 
	if (!(st->had_vehicle_of_type & HVOT_TRAIN)) {
 
		st->had_vehicle_of_type |= HVOT_TRAIN;
 
		SetDParam(0, st->index);
 
		flags = (v->owner == _local_player) ? NEWS_FLAGS(NM_THIN, NF_VIEWPORT|NF_VEHICLE, NT_ARRIVAL_PLAYER, 0) : NEWS_FLAGS(NM_THIN, NF_VIEWPORT|NF_VEHICLE, NT_ARRIVAL_OTHER, 0);
 
		AddNewsItem(
 
			STR_8801_CITIZENS_CELEBRATE_FIRST,
 
			flags,
 
			v->index,
 
			0
 
		);
 
	}
 

	
 
	// Did we reach the final destination?
 
	if (v->current_order.type == OT_GOTO_STATION &&
 
			v->current_order.dest == station) {
 
		// Yeah, keep the load/unload flags
 
		// Non Stop now means if the order should be increased.
 
		v->BeginLoading();
 
		v->current_order.flags &= OF_FULL_LOAD | OF_UNLOAD | OF_TRANSFER;
 
		v->current_order.flags |= OF_NON_STOP;
 
	} else {
 
		// No, just do a simple load
 
		v->BeginLoading();
 
		v->current_order.flags = 0;
 
	}
 
	v->current_order.dest = 0;
 

	
 
	SET_EXPENSES_TYPE(EXPENSES_TRAIN_INC);
 
	if (LoadUnloadVehicle(v, true) != 0) {
 
		InvalidateWindow(WC_TRAINS_LIST, v->owner);
 
		TrainCargoChanged(v);
 
		UpdateTrainAcceleration(v);
 
	}
 
	MarkTrainDirty(v);
 
	InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR);
 
}
 

	
 
static byte AfterSetTrainPos(Vehicle *v, bool new_tile)
 
{
 
	byte new_z, old_z;
 

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

	
 
	old_z = v->z_pos;
0 comments (0 inline, 0 general)