File diff r26193:4bc7915a2156 → r26194:f7347205838e
src/train_cmd.cpp
Show inline comments
 
@@ -100,6 +100,34 @@ void CheckTrainsLengths()
 
}
 

	
 
/**
 
 * Checks the breakdown flags (VehicleRailFlags 9-12) and sets the correct value in the first vehicle of the consist.
 
 * This function is generally only called to check if a flag may be cleared.
 
 * @param v the front engine
 
 * @param flags bitmask of the flags to check.
 
 */
 
void CheckBreakdownFlags(Train *v)
 
{
 
	assert(v->IsFrontEngine());
 
	/* clear the flags we're gonna check first, we'll set them again later (if applicable ) */
 
	CLRBITS(v->flags, (1 << VRF_BREAKDOWN_BRAKING) | VRF_IS_BROKEN);
 

	
 
	for (const Train *w = v; w != NULL; w = w->Next()) {
 
		if (v->IsEngine() || w->IsMultiheaded()) {
 
			if (w->breakdown_ctr == 2) {
 
				SetBit(v->flags, VRF_BREAKDOWN_BRAKING);
 
			} else if (w->breakdown_ctr == 1) {
 
				switch (w->breakdown_type) {
 
					case BREAKDOWN_CRITICAL:
 
					case BREAKDOWN_EM_STOP:   SetBit(v->flags, VRF_BREAKDOWN_STOPPED); break;
 
					case BREAKDOWN_LOW_SPEED: SetBit(v->flags, VRF_BREAKDOWN_SPEED);   break;
 
					case BREAKDOWN_LOW_POWER: SetBit(v->flags, VRF_BREAKDOWN_POWER);   break;
 
				}
 
			}
 
		}
 
	}
 
}
 

	
 
/**
 
 * Recalculates the cached stuff of a train. Should be called each time a vehicle is added
 
 * to/removed from the chain, and when the game is loaded.
 
 * Note: this needs to be called too for 'wagon chains' (in the depot, without an engine)
 
@@ -115,6 +143,7 @@ void Train::ConsistChanged(ConsistChange
 
	EngineID first_engine = this->IsFrontEngine() ? this->engine_type : INVALID_ENGINE;
 
	this->gcache.cached_total_length = 0;
 
	this->compatible_railtypes = RAILTYPES_NONE;
 
	this->tcache.cached_num_engines = 0;
 

	
 
	bool train_can_tilt = true;
 
	int min_curve_speed_mod = INT_MAX;
 
@@ -185,8 +214,13 @@ void Train::ConsistChanged(ConsistChange
 
			/* max speed is the minimum of the speed limits of all vehicles in the consist */
 
			if ((rvi_u->railveh_type != RAILVEH_WAGON || _settings_game.vehicle.wagon_speed_limits) && !UsesWagonOverride(u)) {
 
				uint16 speed = GetVehicleProperty(u, PROP_TRAIN_SPEED, rvi_u->max_speed);
 
				if (HasBit(u->flags, VRF_NEED_REPAIR)) speed = u->vcache.cached_max_speed;
 
				if (speed != 0) max_speed = std::min(speed, max_speed);
 
			}
 

	
 
			if(u->IsEngine() || u-> IsMultiheaded()) {
 
				this->tcache.cached_num_engines++;
 
			}
 
		}
 

	
 
		uint16 new_cap = e_u->DetermineCapacity(u);
 
@@ -420,6 +454,10 @@ int Train::GetCurrentMaxSpeed() const
 
	}
 

	
 
	max_speed = std::min<int>(max_speed, this->current_order.GetMaxSpeed());
 
	if ( HasBit(this->flags, VRF_BREAKDOWN_SPEED) ) {
 
		max_speed = std::min<int>(max_speed, this->GetBreakdownSpeed());
 
	}
 

	
 
	return std::min<int>(max_speed, this->gcache.cached_max_track_speed);
 
}
 

	
 
@@ -432,6 +470,14 @@ void Train::UpdateAcceleration()
 
	uint weight = this->gcache.cached_weight;
 
	assert(weight != 0);
 
	this->acceleration = Clamp(power / weight * 4, 1, 255);
 

	
 
	if (_settings_game.vehicle.improved_breakdowns) {
 
		if (_settings_game.vehicle.train_acceleration_model == AM_ORIGINAL) {
 
			this->breakdown_chance = std::max(128 * 3 / (this->tcache.cached_num_engines + 2), 5);
 
		}
 
	} else {
 
		this->breakdown_chance = 128;
 
	}
 
}
 

	
 
/**
 
@@ -697,6 +743,8 @@ static void AddRearEngineToMultiheadedTr
 
	u->refit_cap = v->refit_cap;
 
	u->railtype = v->railtype;
 
	u->engine_type = v->engine_type;
 
	u->reliability = v->reliability;
 
	u->reliability_spd_dec = v->reliability_spd_dec;
 
	u->date_of_last_service = v->date_of_last_service;
 
	u->build_year = v->build_year;
 
	u->sprite_cache.sprite_seq.Set(SPR_IMG_QUERY);
 
@@ -1936,7 +1984,7 @@ CommandCost CmdReverseTrainDirection(DoC
 
		}
 
	} else {
 
		/* turn the whole train around */
 
		if ((v->vehstatus & VS_CRASHED) || v->breakdown_ctr != 0) return CMD_ERROR;
 
		if ((v->vehstatus & VS_CRASHED) || HasBit(v->flags, VRF_BREAKDOWN_STOPPED)) return CMD_ERROR;
 

	
 
		if (flags & DC_EXEC) {
 
			/* Properly leave the station if we are loading and won't be loading anymore */
 
@@ -2816,6 +2864,25 @@ int Train::UpdateSpeed()
 
			return this->DoUpdateSpeed(this->GetAcceleration(), this->GetAccelerationStatus() == AS_BRAKE ? 0 : 2, this->GetCurrentMaxSpeed());
 
	}
 
}
 
/**
 
 * Handle all breakdown related stuff for a train consist.
 
 * @param v The front engine.
 
 */
 
static bool HandlePossibleBreakdowns(Train *v)
 
{
 
	assert(v->IsFrontEngine());
 
	for (Train *u = v; u != NULL; u = u->Next()) {
 
		if (u->breakdown_ctr != 0 && (u->IsEngine() || u->IsMultiheaded())) {
 
			if (u->breakdown_ctr <= 2) {
 
				if ( u->HandleBreakdown() ) return true;
 
				/* We check the order of v (the first vehicle) instead of u here! */
 
			} else if (!v->current_order.IsType(OT_LOADING)) {
 
				u->breakdown_ctr--;
 
			}
 
		}
 
	}
 
	return false;
 
}
 

	
 
/**
 
 * Trains enters a station, send out a news item if it is the first train, and start loading.
 
@@ -3691,12 +3758,8 @@ static bool TrainCheckIfLineEnds(Train *
 
{
 
	/* First, handle broken down train */
 

	
 
	int t = v->breakdown_ctr;
 
	if (t > 1) {
 
	if(HasBit(v->flags, VRF_BREAKDOWN_BRAKING)) {
 
		v->vehstatus |= VS_TRAIN_SLOWING;
 

	
 
		uint16 break_speed = _breakdown_speeds[GB(~t, 4, 4)];
 
		if (break_speed < v->cur_speed) v->cur_speed = break_speed;
 
	} else {
 
		v->vehstatus &= ~VS_TRAIN_SLOWING;
 
	}
 
@@ -3751,7 +3814,7 @@ static bool TrainLocoHandler(Train *v, b
 
	}
 

	
 
	/* train is broken down? */
 
	if (v->HandleBreakdown()) return true;
 
	if ( HandlePossibleBreakdowns(v) ) return true;
 

	
 
	if (HasBit(v->flags, VRF_REVERSING) && v->cur_speed == 0) {
 
		ReverseTrainDirection(v);
 
@@ -3892,6 +3955,7 @@ Money Train::GetRunningCost() const
 
		if (e->u.rail.running_cost_class == INVALID_PRICE) continue;
 

	
 
		uint cost_factor = GetVehicleProperty(v, PROP_TRAIN_RUNNING_COST_FACTOR, e->u.rail.running_cost);
 
		cost_factor *= _settings_game.economy.running_cost_multiplier_rail;
 
		if (cost_factor == 0) continue;
 

	
 
		/* Halve running cost for multiheaded parts */
 
@@ -3986,7 +4050,6 @@ void Train::OnNewDay()
 
	if ((++this->day_counter & 7) == 0) DecreaseVehicleValue(this);
 

	
 
	if (this->IsFrontEngine()) {
 
		CheckVehicleBreakdown(this);
 

	
 
		CheckIfTrainNeedsService(this);
 

	
 
@@ -4011,6 +4074,9 @@ void Train::OnNewDay()
 
			SetWindowClassesDirty(WC_TRAINS_LIST);
 
		}
 
	}
 
	if(IsEngine() || IsMultiheaded()) {
 
		CheckVehicleBreakdown(this);
 
	}
 
}
 

	
 
/**