cost // running cost of the whole
unc_len // lenght of all parts without a running cost
cal_cost // running cost of all parts (or single part) with a running cost
unc_cost // simulated running cost of all parts (or single part) without a running cost
divisor // user defined value for fine tunning the simulated running cost for each part without a running cost
cal_cost += cal_cost
ind_len // length of current part without running cost
ind_cost = (unc_len * cal_cost * ind_len) / (VEHICLE_LENGTH * divisor * 2)
unc_cost += ind_cost
cost = unc_cost + cal_cost
/**
* Get running cost for the train consist or only for the current part.
*
* @param single_part whether to return the running cost of the current part or the whole.
* @return Yearly running costs.
*/
Money Train::GetRunningCost(bool single_part) const
{
Money cost = 0; // running cost of the whole
uint unc_len = 0; // lenght of all parts without a running cost
Money cal_cost = 0; // running cost of all parts (or single part) with a running cost
Money unc_cost = 0; // simulated running cost of all parts (or single part) without a running cost
uint divisor = 0; // user defined value for fine tunning the simulated running cost for each part without a running cost
if (_settings_game.vehicle.train_extra_runcost_divisor == 0) {
divisor = VEHICLE_LENGTH * 2 * _settings_game.vehicle.max_train_length;
} else {
divisor = VEHICLE_LENGTH * 2 * _settings_game.vehicle.train_extra_runcost_divisor;
}
const Train *v = this;
const Train *v1 = single_part ? v->First() : v;
const Train *v2 = v1;
do {
const Engine *e = v1->GetEngine();
if (e->u.rail.running_cost_class == INVALID_PRICE) {
const Train *a = v1;
do {
unc_len += a->gcache.cached_veh_length;
a = a->HasArticulatedPart() ? a->GetNextArticulatedPart() : NULL;
} while (a != NULL);
continue;
}
uint cost_factor = GetVehicleProperty(v1, PROP_TRAIN_RUNNING_COST_FACTOR, e->u.rail.running_cost);
if (cost_factor == 0) continue;
/* Halve running cost for multiheaded parts */
if (v1->IsMultiheaded()) cost_factor /= 2;
cal_cost += GetPrice(e->u.rail.running_cost_class, cost_factor, e->GetGRF());
} while ((v1 = v1->GetNextVehicle()) != NULL);
if (_settings_game.vehicle.train_extra_runcost && unc_len > 0 && cal_cost > 0) {
do {
const Engine *e = v2->GetEngine();
if (e->u.rail.running_cost_class != INVALID_PRICE) continue;
const Train *a = v2;
uint ind_len = 0; // length of current part without running cost
do {
ind_len += a->gcache.cached_veh_length;
a = a->HasArticulatedPart() ? a->GetNextArticulatedPart() : NULL;
} while (a != NULL);
if (ind_len == 0) continue;
Money ind_cost = (unc_len * cal_cost * ind_len) / (VEHICLE_LENGTH * divisor * 2);
uint cost_factor = GetVehicleProperty(v2, PROP_TRAIN_RUNNING_COST_FACTOR, ind_cost);
/* Halve running cost for multiheaded parts */
if (v2->IsMultiheaded()) cost_factor /= 2;
unc_cost += GetPrice(PR_RUNNING_TRAIN_STEAM, cost_factor, e->GetGRF()) / _price[PR_RUNNING_TRAIN_STEAM];
} while ((v2 = v2->GetNextVehicle()) != NULL);
}
cost = unc_cost + cal_cost;
if (!single_part) return cost;
const Engine *e = v->GetEngine();
if (e->u.rail.running_cost_class == INVALID_PRICE) {
if (!_settings_game.vehicle.train_extra_runcost) return unc_cost;
const Train *a = v;
uint ind_len = 0; // length of current part without running cost
do {
ind_len += a->gcache.cached_veh_length;
a = a->HasArticulatedPart() ? a->GetNextArticulatedPart() : NULL;
} while (a != NULL);
Money ind_cost = (unc_len * cal_cost * ind_len) / (VEHICLE_LENGTH * divisor * 2);
uint cost_factor = GetVehicleProperty(v, PROP_TRAIN_RUNNING_COST_FACTOR, ind_cost);
/* Halve running cost for multiheaded parts */
if (v->IsMultiheaded()) cost_factor /= 2;
unc_cost = GetPrice(PR_RUNNING_TRAIN_STEAM, cost_factor, e->GetGRF()) / _price[PR_RUNNING_TRAIN_STEAM];
return unc_cost;
} else {
uint cost_factor = GetVehicleProperty(v, PROP_TRAIN_RUNNING_COST_FACTOR, e->u.rail.running_cost);
/* Halve running cost for multiheaded parts */
if (v->IsMultiheaded()) cost_factor /= 2;
cal_cost = GetPrice(e->u.rail.running_cost_class, cost_factor, e->GetGRF());
return cal_cost;
}
}