Index: lang/english.txt =================================================================== --- lang/english.txt (revision 27764) +++ lang/english.txt (working copy) @@ -3689,7 +3689,9 @@ # Extra buttons for train details windows STR_VEHICLE_DETAILS_TRAIN_ENGINE_BUILT_AND_VALUE :{LTBLUE}{ENGINE}{BLACK} Built: {LTBLUE}{NUM}{BLACK} Value: {LTBLUE}{CURRENCY_LONG} +STR_VEHICLE_DETAILS_TRAIN_ENGINE_BUILT_VALUE_RUNCOST :{LTBLUE}{ENGINE}{BLACK} Built: {LTBLUE}{NUM}{BLACK} Value: {LTBLUE}{CURRENCY_LONG}{BLACK} Running Cost: {LTBLUE}{CURRENCY_LONG}/yr STR_VEHICLE_DETAILS_TRAIN_WAGON_VALUE :{LTBLUE}{ENGINE}{BLACK} Value: {LTBLUE}{CURRENCY_LONG} +STR_VEHICLE_DETAILS_TRAIN_WAGON_VALUE_RUNCOST :{LTBLUE}{ENGINE}{BLACK} Value: {LTBLUE}{CURRENCY_LONG}{BLACK} Running Cost: {LTBLUE}{CURRENCY_LONG}/yr STR_VEHICLE_DETAILS_TRAIN_TOTAL_CAPACITY_TEXT :{BLACK}Total cargo capacity of this train: STR_VEHICLE_DETAILS_TRAIN_TOTAL_CAPACITY :{LTBLUE}- {CARGO_LONG} ({CARGO_SHORT}) Index: train.h =================================================================== --- train.h (revision 27764) +++ train.h (working copy) @@ -117,7 +117,7 @@ void GetImage(Direction direction, EngineImageType image_type, VehicleSpriteSeq *result) const; int GetDisplaySpeed() const { return this->gcache.last_speed; } int GetDisplayMaxSpeed() const { return this->vcache.cached_max_speed; } - Money GetRunningCost() const; + Money GetRunningCost(bool single_part = false) const; int GetDisplayImageWidth(Point *offset = NULL) const; bool IsInDepot() const { return this->track == TRACK_BIT_DEPOT; } bool Tick(); Index: train_cmd.cpp =================================================================== --- train_cmd.cpp (revision 27764) +++ train_cmd.cpp (working copy) @@ -3897,25 +3897,84 @@ * Get running cost for the train consist. * @return Yearly running costs. */ -Money Train::GetRunningCost() const +Money Train::GetRunningCost(bool single_part) const { Money cost = 0; const Train *v = this; + const Train *v1 = single_part ? v->First() : v; + const Train *v2 = v1; + bool unc_len = false; + uint cal_cost = 0; + uint unc_cost = 0; do { - const Engine *e = v->GetEngine(); - if (e->u.rail.running_cost_class == INVALID_PRICE) continue; + const Engine *e = v1->GetEngine(); + if (e->u.rail.running_cost_class == INVALID_PRICE) { + unc_len = true; + continue; + } - uint cost_factor = GetVehicleProperty(v, PROP_TRAIN_RUNNING_COST_FACTOR, e->u.rail.running_cost); + 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 (unc_len && 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; + do { + ind_len += a->gcache.cached_veh_length; + a = a->HasArticulatedPart() ? a->GetNextArticulatedPart() : NULL; + } while (a != NULL); + if (ind_len == 0) continue; + + uint ind_cost = cal_cost * ind_len / (VEHICLE_LENGTH * 2 * _settings_game.vehicle.max_train_length); + uint cost_factor = GetEngineProperty(e->index, 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) { + const Train *a = v; + uint ind_len = 0; + do { + ind_len += a->gcache.cached_veh_length; + a = a->HasArticulatedPart() ? a->GetNextArticulatedPart() : NULL; + } while (a != NULL); + + uint ind_cost = cal_cost * ind_len / (VEHICLE_LENGTH * 2 * _settings_game.vehicle.max_train_length); + uint cost_factor = GetEngineProperty(e->index, PROP_TRAIN_RUNNING_COST_FACTOR, ind_cost); + + /* Halve running cost for multiheaded parts */ if (v->IsMultiheaded()) cost_factor /= 2; - cost += GetPrice(e->u.rail.running_cost_class, cost_factor, e->GetGRF()); - } while ((v = v->GetNextVehicle()) != NULL); + 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); - return 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; + } } /** Index: train_gui.cpp =================================================================== --- train_gui.cpp (revision 27764) +++ train_gui.cpp (working copy) @@ -222,12 +222,14 @@ if (RailVehInfo(v->engine_type)->railveh_type == RAILVEH_WAGON) { SetDParam(0, v->engine_type); SetDParam(1, v->value); - DrawString(left, right, y, STR_VEHICLE_DETAILS_TRAIN_WAGON_VALUE); + SetDParam(2, v->GetRunningCost(true) >> 8); + DrawString(left, right, y, STR_VEHICLE_DETAILS_TRAIN_WAGON_VALUE_RUNCOST); } else { SetDParam(0, v->engine_type); SetDParam(1, v->build_year); SetDParam(2, v->value); - DrawString(left, right, y, STR_VEHICLE_DETAILS_TRAIN_ENGINE_BUILT_AND_VALUE); + SetDParam(3, v->GetRunningCost(true) >> 8); + DrawString(left, right, y, STR_VEHICLE_DETAILS_TRAIN_ENGINE_BUILT_VALUE_RUNCOST); } } Index: vehicle_base.h =================================================================== --- vehicle_base.h (revision 27764) +++ vehicle_base.h (working copy) @@ -495,7 +495,7 @@ * Gets the running cost of a vehicle * @return the vehicle's running cost */ - virtual Money GetRunningCost() const { return 0; } + virtual Money GetRunningCost(bool single_part = false) const { return 0; } /** * Check whether the vehicle is in the depot.