From e9e4ba822215abdcd5403dfd1517c52a631acb3a Mon Sep 17 00:00:00 2001 From: peter1138 Date: Thu, 28 Dec 2006 13:18:07 +0000 Subject: [PATCH] (svn r7592) -Feature: Add support for tractive effort to 'realistic' acceleration. --- engine.h | 1 + lang/english.txt | 2 + newgrf.c | 6 ++- table/engines.h | 3 +- train_cmd.c | 99 +++++++++++++++++++++++++++--------------------- train_gui.c | 12 +++++- vehicle.h | 1 + 7 files changed, 78 insertions(+), 46 deletions(-) diff --git a/engine.h b/engine.h index a0b355874f..2fa6b9eb0b 100644 --- a/engine.h +++ b/engine.h @@ -27,6 +27,7 @@ typedef struct RailVehicleInfo { // kind of visual effect to generate for a vehicle (default, steam, diesel, electric). // Same goes for the callback result, which atm is only used to check if a wagon is powered. byte shorten_factor; // length on main map for this type is 8 - shorten_factor + byte tractive_effort; ///< Tractive effort coefficient byte user_def_data; ///! Property 0x25: "User-defined bit mask" Used only for (very few) NewGRF vehicles } RailVehicleInfo; diff --git a/lang/english.txt b/lang/english.txt index 3306dedc63..59d22d20d1 100644 --- a/lang/english.txt +++ b/lang/english.txt @@ -2604,6 +2604,7 @@ STR_VEHICLE_INFO_COST_WEIGHT_SPEED_POWER :{BLACK}Cost: {C STR_885C_BROKEN_DOWN :{RED}Broken down STR_885D_AGE_RUNNING_COST_YR :{BLACK}Age: {LTBLUE}{STRING2}{BLACK} Running Cost: {LTBLUE}{CURRENCY}/yr STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED :{BLACK}Weight: {LTBLUE}{WEIGHT_S} {BLACK}Power: {LTBLUE}{POWER}{BLACK} Max. speed: {LTBLUE}{VELOCITY} +STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED_MAX_TE :{BLACK}Weight: {LTBLUE}{WEIGHT_S} {BLACK}Power: {LTBLUE}{POWER}{BLACK} Max. speed: {LTBLUE}{VELOCITY} {BLACK}Max. T.E.: {LTBLUE}{FORCE} STR_885F_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Profit this year: {LTBLUE}{CURRENCY} (last year: {CURRENCY}) STR_8860_RELIABILITY_BREAKDOWNS :{BLACK}Reliability: {LTBLUE}{COMMA}% {BLACK}Breakdowns since last service: {LTBLUE}{COMMA} STR_8861_STOPPED :{RED}Stopped @@ -3045,6 +3046,7 @@ STR_PURCHASE_INFO_PWAGPOWER_PWAGWEIGHT :{BLACK}Powered STR_PURCHASE_INFO_REFITTABLE_TO :{BLACK}Refittable to: {GOLD} STR_PURCHASE_INFO_ALL_TYPES :All cargo types STR_PURCHASE_INFO_ALL_BUT :All but {GOLD} +STR_PURCHASE_INFO_MAX_TE :{BLACK}Max. Tractive Effort: {GOLD}{FORCE} ########### String for New Landscape Generator diff --git a/newgrf.c b/newgrf.c index 60a16a46b8..ea91c1e33e 100644 --- a/newgrf.c +++ b/newgrf.c @@ -416,6 +416,10 @@ static bool RailVehicleChangeInfo(uint engine, int numinfo, int prop, byte **buf FOR_EACH_OBJECT ei[i].callbackmask = grf_load_byte(&buf); break; + case 0x1F: /* Tractive effort coefficient */ + FOR_EACH_OBJECT rvi[i].tractive_effort = grf_load_byte(&buf); + break; + case 0x21: /* Shorter vehicle */ FOR_EACH_OBJECT rvi[i].shorten_factor = grf_load_byte(&buf); break; @@ -466,7 +470,6 @@ static bool RailVehicleChangeInfo(uint engine, int numinfo, int prop, byte **buf /* TODO */ /* Fall-through for unimplemented one byte long properties. */ - case 0x1F: /* Tractive effort */ case 0x20: /* Air drag */ case 0x26: /* Retire vehicle early */ /* TODO */ @@ -3692,3 +3695,4 @@ void LoadNewGRF(uint load_index, uint file_index) CalculateRefitMasks(); } + diff --git a/table/engines.h b/table/engines.h index 40389082af..08c4cea007 100644 --- a/table/engines.h +++ b/table/engines.h @@ -341,8 +341,9 @@ const EngineInfo orig_engine_info[] = { * @param i capacity * @param j cargo_type * @param k ai_rank + * Tractive effort coefficient by default is the same as TTDPatch, 0.30*256=76 */ -#define RVI(a, b, c, d, e, f, g, h, i, j, k) { a, b, c, d, e, f, g, h, h, i, j, k, 0, 0, 0, 0, 0 } +#define RVI(a, b, c, d, e, f, g, h, i, j, k) { a, b, c, d, e, f, g, h, h, i, j, k, 0, 0, 0, 0, 76, 0 } #define M RVI_MULTIHEAD #define W RVI_WAGON #define S 0 diff --git a/train_cmd.c b/train_cmd.c index 5a4148f92a..c1c5746bb4 100644 --- a/train_cmd.c +++ b/train_cmd.c @@ -54,6 +54,54 @@ byte FreightWagonMult(CargoID cargo) } +/** + * Recalculates the cached total power of a train. Should be called when the consist is changed + * @param v First vehicle of the consist. + */ +void TrainPowerChanged(Vehicle* v) +{ + Vehicle* u; + uint32 power = 0; + uint32 max_te = 0; + + for (u = v; u != NULL; u = u->next) { + const RailVehicleInfo *rvi_u; + bool engine_has_power = true; + bool wagon_has_power = true; + + /* Power is not added for articulated parts */ + if (IsArticulatedPart(u)) continue; + + if (IsLevelCrossingTile(u->tile)) { + if (!HasPowerOnRail(u->u.rail.railtype, GetRailTypeCrossing(u->tile))) engine_has_power = false; + if (!HasPowerOnRail(v->u.rail.railtype, GetRailTypeCrossing(u->tile))) wagon_has_power = false; + } else { + if (!HasPowerOnRail(u->u.rail.railtype, GetRailType(u->tile))) engine_has_power = false; + if (!HasPowerOnRail(v->u.rail.railtype, GetRailType(u->tile))) wagon_has_power = false; + } + + rvi_u = RailVehInfo(u->engine_type); + + if (engine_has_power && rvi_u->power != 0) { + power += rvi_u->power; + /* Tractive effort in (tonnes * 1000 * 10 =) N */ + max_te += (u->u.rail.cached_veh_weight * 10000 * rvi_u->tractive_effort) / 256; + } + + if (HASBIT(u->u.rail.flags, VRF_POWEREDWAGON) && (wagon_has_power)) { + power += RailVehInfo(u->u.rail.first_engine)->pow_wag_power; + } + } + + if (v->u.rail.cached_power != power || v->u.rail.cached_max_te != max_te) { + v->u.rail.cached_power = power; + v->u.rail.cached_max_te = max_te; + InvalidateWindow(WC_VEHICLE_DETAILS, v->index); + InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR); + } +} + + /** * Recalculates the cached weight of a train and its vehicles. Should be called each time the cargo on * the consist changes. @@ -87,47 +135,11 @@ static void TrainCargoChanged(Vehicle* v) // store consist weight in cache v->u.rail.cached_weight = weight; + + /* Now update train power (tractive effort is dependent on weight) */ + TrainPowerChanged(v); } -/** - * Recalculates the cached total power of a train. Should be called when the consist is changed - * @param v First vehicle of the consist. - */ -void TrainPowerChanged(Vehicle* v) -{ - Vehicle* u; - uint32 power = 0; - - for (u = v; u != NULL; u = u->next) { - const RailVehicleInfo *rvi_u; - bool engine_has_power = true; - bool wagon_has_power = true; - - /* Power is not added for articulated parts */ - if (IsArticulatedPart(u)) continue; - - if (IsLevelCrossingTile(u->tile)) { - if (!HasPowerOnRail(u->u.rail.railtype, GetRailTypeCrossing(u->tile))) engine_has_power = false; - if (!HasPowerOnRail(v->u.rail.railtype, GetRailTypeCrossing(u->tile))) wagon_has_power = false; - } else { - if (!HasPowerOnRail(u->u.rail.railtype, GetRailType(u->tile))) engine_has_power = false; - if (!HasPowerOnRail(v->u.rail.railtype, GetRailType(u->tile))) wagon_has_power = false; - } - - rvi_u = RailVehInfo(u->engine_type); - - if (engine_has_power) power += rvi_u->power; - if (HASBIT(u->u.rail.flags, VRF_POWEREDWAGON) && (wagon_has_power)) { - power += RailVehInfo(u->u.rail.first_engine)->pow_wag_power; - } - } - - if (v->u.rail.cached_power != power) { - v->u.rail.cached_power = power; - InvalidateWindow(WC_VEHICLE_DETAILS, v->index); - InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR); - } -} /** * Recalculates the cached stuff of a train. Should be called each time a vehicle is added @@ -231,9 +243,7 @@ void TrainConsistChanged(Vehicle* v) // store consist weight/max speed in cache v->u.rail.cached_max_speed = max_speed; - TrainPowerChanged(v); - - // recalculate cached weights too (we do this *after* the rest, so it is known which wagons are powered and need extra weight added) + // recalculate cached weights and power too (we do this *after* the rest, so it is known which wagons are powered and need extra weight added) TrainCargoChanged(v); } @@ -307,6 +317,7 @@ static int GetTrainAcceleration(Vehicle *v, bool mode) int curvecount[2] = {0, 0}; int sum = 0; int numcurve = 0; + int max_te = v->u.rail.cached_max_te; // [N] speed *= 10; speed /= 16; @@ -407,6 +418,7 @@ static int GetTrainAcceleration(Vehicle *v, bool mode) force = power / speed; //[N] force *= 22; force /= 10; + if (mode == AM_ACCEL && force > max_te) force = max_te; break; case RAILTYPE_MAGLEV: @@ -415,7 +427,8 @@ static int GetTrainAcceleration(Vehicle *v, bool mode) } } else { //"kickoff" acceleration - force = max(power, (mass * 8) + resistance); + force = (mode == AM_ACCEL && v->u.rail.railtype != RAILTYPE_MAGLEV) ? min(max_te, power) : power; + force = max(force, (mass * 8) + resistance); } if (force <= 0) force = 10000; diff --git a/train_gui.c b/train_gui.c index f3e461bbc6..479d0a0c4f 100644 --- a/train_gui.c +++ b/train_gui.c @@ -232,6 +232,13 @@ void DrawTrainEnginePurchaseInfo(int x, int y, uint w, EngineID engine_number) DrawString(x,y, STR_PURCHASE_INFO_SPEED_POWER, 0); y += 10; + /* Max tractive effort - not applicable if old acceleration or maglev */ + if (_patches.realistic_acceleration && e->railtype != RAILTYPE_MAGLEV) { + SetDParam(0, ((rvi->weight << multihead) * 10 * rvi->tractive_effort) / 256); + DrawString(x, y, STR_PURCHASE_INFO_MAX_TE, 0); + y += 10; + } + /* Running cost */ SetDParam(0, (rvi->running_cost_base * _price.running_rail[rvi->running_cost_class] >> 8) << multihead); DrawString(x,y, STR_PURCHASE_INFO_RUNNINGCOST, 0); @@ -939,7 +946,10 @@ static void DrawTrainDetailsWindow(Window *w) SetDParam(2, v->u.rail.cached_max_speed); SetDParam(1, v->u.rail.cached_power); SetDParam(0, v->u.rail.cached_weight); - DrawString(x, 25, STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED, 0); + SetDParam(3, v->u.rail.cached_max_te / 1000); + DrawString(x, 25, (_patches.realistic_acceleration && v->u.rail.railtype != RAILTYPE_MAGLEV) ? + STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED_MAX_TE : + STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED, 0); SetDParam(0, v->profit_this_year); SetDParam(1, v->profit_last_year); diff --git a/vehicle.h b/vehicle.h index 80f3939c4f..10ca04903b 100644 --- a/vehicle.h +++ b/vehicle.h @@ -62,6 +62,7 @@ typedef struct VehicleRail { // cached values, recalculated when the cargo on a train changes (in addition to the conditions above) uint32 cached_weight; // total weight of the consist. uint32 cached_veh_weight; // weight of the vehicle. + uint32 cached_max_te; // max tractive effort of consist /** * Position/type of visual effect. * bit 0 - 3 = position of effect relative to vehicle. (0 = front, 8 = centre, 15 = rear)