diff --git a/engine.c b/engine.c --- a/engine.c +++ b/engine.c @@ -589,6 +589,16 @@ int GetCustomEngineSprite(byte engine, c } /** + * Check if a wagon is currently using a wagon override + * @param v The wagon to check + * @return true if it is using an override, false otherwise + */ +bool UsesWagonOverride(const Vehicle *v) { + assert(v->type == VEH_Train); + return (GetWagonOverrideSpriteSet(v->engine_type, v->u.rail.first_engine) != NULL); +} + +/** * Evaluates a newgrf callback * @param callback_info info about which callback to evaluate * (bit 0-7) = CallBack id of the callback to use, see CallBackId enum diff --git a/engine.h b/engine.h --- a/engine.h +++ b/engine.h @@ -15,6 +15,12 @@ typedef struct RailVehicleInfo { byte capacity; byte cargo_type; byte callbackmask; // see CallbackMask enum + uint16 pow_wag_power; + byte pow_wag_weight; + byte visual_effect; // NOTE: this is not 100% implemented yet, at the moment it is only used as a 'fallback' value + // for when the 'powered wagon' callback fails. But it should really also determine what + // 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. } RailVehicleInfo; typedef struct ShipVehicleInfo { @@ -126,6 +132,10 @@ enum GlobalCargo { // This enum lists the implemented callbacks // Use as argument for the GetCallBackResult function (see comments there) enum CallbackID { + // Powered wagons, if the result is lower as 0x40 then the wagon is powered + // TODO: interpret the rest of the result, aka "visual effects" + CBID_WAGON_POWER = 0x10, + // Refit capacity, the passed vehicle needs to have its ->cargo_type set to // the cargo we are refitting to, returns the new cargo capacity CBID_REFIT_CAP = 0x15, @@ -153,6 +163,7 @@ void SetCustomEngineSprites(byte engine, // loaded is in percents, overriding_engine 0xffff is none int GetCustomEngineSprite(byte engine, const Vehicle *v, byte direction); uint16 GetCallBackResult(uint16 callback_info, byte engine, const Vehicle *v); +bool UsesWagonOverride(const Vehicle *v); #define GetCustomVehicleSprite(v, direction) GetCustomEngineSprite(v->engine_type, v, direction) #define GetCustomVehicleIcon(et, direction) GetCustomEngineSprite(et, NULL, direction) diff --git a/lang/english.txt b/lang/english.txt --- a/lang/english.txt +++ b/lang/english.txt @@ -2829,3 +2829,4 @@ STR_PURCHASE_INFO_COST STR_PURCHASE_INFO_WEIGHT_CWEIGHT :{BLACK}Weight: {GOLD}{COMMA16}t ({COMMA16}t) STR_PURCHASE_INFO_COST_SPEED :{BLACK}Cost: {GOLD}{CURRENCY}{BLACK} Speed: {GOLD}{VELOCITY} STR_PURCHASE_INFO_AIRCRAFT_CAPACITY :{BLACK}Capacity: {GOLD}{COMMA16} passengers, {COMMA16} bags of mail +STR_PURCHASE_INFO_PWAGPOWER_PWAGWEIGHT :{BLACK}Powered Wagons: {GOLD}+{COMMA16}hp{BLACK} Weight: {GOLD}+{COMMA8}t diff --git a/newgrf.c b/newgrf.c --- a/newgrf.c +++ b/newgrf.c @@ -198,30 +198,30 @@ static bool RailVehicleChangeInfo(uint e bool ret = false; switch (prop) { - case 0x05: { /* Track type */ + case 0x05: { /* Track type */ FOR_EACH_OBJECT { uint8 tracktype = grf_load_byte(&buf); ei[i].railtype_climates &= 0xf; ei[i].railtype_climates |= tracktype << 4; } - } break; - case 0x08: { /* AI passenger service */ + } break; + case 0x08: { /* AI passenger service */ /* TODO */ FOR_EACH_OBJECT { grf_load_byte(&buf); } ret = true; - } break; - case 0x09: { /* Speed */ + } break; + case 0x09: { /* Speed */ FOR_EACH_OBJECT { uint16 speed = grf_load_word(&buf); rvi[i].max_speed = speed; dewagonize(speed, engine + i); } - } break; - case 0x0B: { /* Power */ + } break; + case 0x0B: { /* Power */ FOR_EACH_OBJECT { uint16 power = grf_load_word(&buf); @@ -231,16 +231,16 @@ static bool RailVehicleChangeInfo(uint e rvi[i].power = power; dewagonize(power, engine + i); } - } break; - case 0x0D: { /* Running cost factor */ + } break; + case 0x0D: { /* Running cost factor */ FOR_EACH_OBJECT { uint8 runcostfact = grf_load_byte(&buf); rvi[i].running_cost_base = runcostfact; dewagonize(runcostfact, engine + i); } - } break; - case 0x0E: { /* Running cost base */ + } break; + case 0x0E: { /* Running cost base */ FOR_EACH_OBJECT { uint32 base = grf_load_dword(&buf); @@ -257,8 +257,8 @@ static bool RailVehicleChangeInfo(uint e } dewagonize(base, engine + i); } - } break; - case 0x12: { /* Sprite ID */ + } break; + case 0x12: { /* Sprite ID */ FOR_EACH_OBJECT { uint8 spriteid = grf_load_byte(&buf); @@ -266,8 +266,8 @@ static bool RailVehicleChangeInfo(uint e _engine_original_sprites[engine + i] = rvi[i].image_index; rvi[i].image_index = spriteid; } - } break; - case 0x13: { /* Dual-headed */ + } break; + case 0x13: { /* Dual-headed */ FOR_EACH_OBJECT { uint8 dual = grf_load_byte(&buf); @@ -281,42 +281,42 @@ static bool RailVehicleChangeInfo(uint e rvi[i].flags &= ~RVI_MULTIHEAD; } } - } break; - case 0x14: { /* Cargo capacity */ + } break; + case 0x14: { /* Cargo capacity */ FOR_EACH_OBJECT { uint8 capacity = grf_load_byte(&buf); rvi[i].capacity = capacity; } - } break; - case 0x15: { /* Cargo type */ + } break; + case 0x15: { /* Cargo type */ FOR_EACH_OBJECT { uint8 ctype = grf_load_byte(&buf); rvi[i].cargo_type = ctype; } - } break; - case 0x16: { /* Weight */ + } break; + case 0x16: { /* Weight */ FOR_EACH_OBJECT { uint8 weight = grf_load_byte(&buf); rvi[i].weight = weight; } - } break; - case 0x17: { /* Cost factor */ + } break; + case 0x17: { /* Cost factor */ FOR_EACH_OBJECT { uint8 cfactor = grf_load_byte(&buf); rvi[i].base_cost = cfactor; } - } break; - case 0x18: { /* AI rank */ + } break; + case 0x18: { /* AI rank */ /* TODO: _railveh_score should be merged to _rail_vehicle_info. */ FOR_EACH_OBJECT { grf_load_byte(&buf); } ret = true; - } break; + } break; case 0x19: { /* Engine traction type */ /* TODO: What do the individual numbers mean? * XXX: And in what base are they, in fact? --pasky */ @@ -335,34 +335,49 @@ static bool RailVehicleChangeInfo(uint e rvi[i].engclass = engclass; } - } break; - case 0x1D: { /* Refit cargo */ + } break; + case 0x1B: { /* Powered wagons power bonus */ + FOR_EACH_OBJECT { + uint16 wag_power = grf_load_word(&buf); + + rvi[i].pow_wag_power = wag_power; + } + } break; + case 0x1D: { /* Refit cargo */ FOR_EACH_OBJECT { uint32 refit_mask = grf_load_dword(&buf); _engine_refit_masks[engine + i] = refit_mask; } - } break; - case 0x1E: /* Callback */ + } break; + case 0x1E: { /* Callback */ FOR_EACH_OBJECT { byte callbacks = grf_load_byte(&buf); rvi[i].callbackmask = callbacks; } - break; + } break; + case 0x22: { /* Visual effect */ + // see note in engine.h about rvi->visual_effect + FOR_EACH_OBJECT { + byte visual = grf_load_byte(&buf); + + rvi[i].visual_effect = visual; + } + } break; + case 0x23: { /* Powered wagons weight bonus */ + FOR_EACH_OBJECT { + byte wag_weight = grf_load_byte(&buf); + + rvi[i].pow_wag_weight = wag_weight; + } + } break; /* TODO */ - /* Fall-through for unimplemented two bytes long properties. */ - case 0x1B: /* Powered wagons power bonus */ - FOR_EACH_OBJECT { - grf_load_byte(&buf); - } /* Fall-through for unimplemented one byte long properties. */ case 0x1A: /* Sort order */ case 0x1C: /* Refit cost */ case 0x1F: /* Tractive effort */ case 0x20: /* Air drag */ case 0x21: /* Shorter tenders */ - case 0x22: /* Visual */ - case 0x23: /* Powered wagons weight bonus */ case 0x24: /* High byte of vehicle weight */ case 0x25: /* User-defined bit mask to set when checking veh. var. 42 */ case 0x26: /* Retire vehicle early */ @@ -388,28 +403,28 @@ static bool RoadVehicleChangeInfo(uint e bool ret = false; switch (prop) { - case 0x08: { /* Speed */ + case 0x08: { /* Speed */ FOR_EACH_OBJECT { uint8 speed = grf_load_byte(&buf); rvi[i].max_speed = speed; // ?? units } } break; - case 0x09: { /* Running cost factor */ + case 0x09: { /* Running cost factor */ FOR_EACH_OBJECT { uint8 runcost = grf_load_byte(&buf); rvi[i].running_cost = runcost; } } break; - case 0x0A: /* Running cost base */ + case 0x0A: { /* Running cost base */ /* TODO: I have no idea. --pasky */ FOR_EACH_OBJECT { grf_load_byte(&buf); } ret = true; - break; - case 0x0E: { /* Sprite ID */ + } break; + case 0x0E: { /* Sprite ID */ FOR_EACH_OBJECT { uint8 spriteid = grf_load_byte(&buf); @@ -424,7 +439,7 @@ static bool RoadVehicleChangeInfo(uint e rvi[i].image_index = spriteid; } } break; - case 0x0F: { /* Cargo capacity */ + case 0x0F: { /* Cargo capacity */ FOR_EACH_OBJECT { uint16 capacity = grf_load_word(&buf); @@ -438,14 +453,14 @@ static bool RoadVehicleChangeInfo(uint e rvi[i].cargo_type = cargo; } } break; - case 0x11: { /* Cost factor */ + case 0x11: { /* Cost factor */ FOR_EACH_OBJECT { uint8 cost_factor = grf_load_byte(&buf); rvi[i].base_cost = cost_factor; // ?? is it base_cost? } } break; - case 0x12: { /* SFX */ + case 0x12: { /* SFX */ FOR_EACH_OBJECT { uint8 sfx = grf_load_byte(&buf); diff --git a/table/engines.h b/table/engines.h --- a/table/engines.h +++ b/table/engines.h @@ -267,126 +267,126 @@ EngineInfo _engine_info[TOTAL_NUM_ENGINE RailVehicleInfo _rail_vehicle_info[NUM_TRAIN_ENGINES] = { // image_index max_speed (kph) running_cost_base callback bitmask - // | flags | power (hp) | running_cost_class | - // | | base_cost | weight | capacity | - // | | | | | | | | | cargo_type | - // | | | | | | | | | | | - { 2, 0, 7, 64, 300, 47, 50, 0, 0, 0 , 0 }, /* 0 */ - { 19, 0, 8, 80, 600, 65, 65, 1, 0, 0 , 0 }, /* 1 */ - { 2, 0, 10, 72, 400, 85, 90, 0, 0, 0 , 0 }, /* 2 */ - { 0, 0, 15, 96, 900, 130, 130, 0, 0, 0 , 0 }, /* 3 */ - { 1, 0, 19, 112, 1000, 140, 145, 0, 0, 0 , 0 }, /* 4 */ - { 12, 0, 16, 120, 1400, 95, 125, 1, 0, 0 , 0 }, /* 5 */ - { 14, 0, 20, 152, 2000, 120, 135, 1, 0, 0 , 0 }, /* 6 */ - { 3, 0, 14, 88, 1100, 145, 130, 0, 0, 0 , 0 }, /* 7 */ - { 0, 0, 13, 112, 1000, 131, 120, 0, 0, 0 , 0 }, /* 8 */ - { 1, 0, 19, 128, 1200, 162, 140, 0, 0, 0 , 0 }, /* 9 */ - { 0, 0, 22, 144, 1600, 170, 130, 0, 0, 0 , 0 }, /* 10 */ - { 8, 1, 11, 112, 600/2,32/2, 85/2, 1, 38, CT_PASSENGERS , 0 }, /* 11 */ - { 10, 1, 14, 120, 700/2,38/2, 70/2, 1, 40, CT_PASSENGERS , 0 }, /* 12 */ - { 4, 0, 15, 128, 1250, 72, 95, 1, 0, 0 , 0 }, /* 13 */ - { 5, 0, 17, 144, 1750, 101, 120, 1, 0, 0 , 0 }, /* 14 */ - { 4, 0, 18, 160, 2580, 112, 140, 1, 0, 0 , 0 }, /* 15 */ - { 14, 0, 23, 96, 4000, 150, 135, 1, 0, 0 , 0 }, /* 16 */ - { 12, 0, 16, 112, 2400, 120, 105, 1, 0, 0 , 0 }, /* 17 */ - { 13, 0, 30, 112, 6600, 207, 155, 1, 0, 0 , 0 }, /* 18 */ - { 15, 0, 18, 104, 1500, 110, 105, 1, 0, 0 , 0 }, /* 19 */ - { 16, 1, 35, 160, 3500/2,95/2, 205/2, 1, 0, 0 , 0 }, /* 20 */ - { 18, 0, 21, 104, 2200, 120, 145, 1, 0, 0 , 0 }, /* 21 */ - { 6, 1, 20, 200, 4500/2,70/2, 190/2, 1, 4, CT_MAIL , 0 }, /* 22 */ - { 20, 0, 26, 160, 3600, 84, 180, 2, 0, 0 , 0 }, /* 23 */ - { 20, 0, 30, 176, 5000, 82, 205, 2, 0, 0 , 0 }, /* 24 */ - { 21, 1, 40, 240, 7000/2,90/2, 240/2, 2, 0, 0 , 0 }, /* 25 */ - { 23, 1, 43, 264, 8000/2,95/2, 250/2, 2, 0, 0 , 0 }, /* 26 */ - { 33, 2, 247, 0, 0, 25, 0, 0, 40, CT_PASSENGERS , 0 }, /* 27 */ - { 35, 2, 228, 0, 0, 21, 0, 0, 30, CT_MAIL , 0 }, /* 28 */ - { 34, 2, 176, 0, 0, 18, 0, 0, 30, CT_COAL , 0 }, /* 29 */ - { 36, 2, 200, 0, 0, 24, 0, 0, 30, CT_OIL , 0 }, /* 30 */ - { 37, 2, 192, 0, 0, 20, 0, 0, 25, CT_LIVESTOCK , 0 }, /* 31 */ - { 38, 2, 190, 0, 0, 21, 0, 0, 25, CT_GOODS , 0 }, /* 32 */ - { 39, 2, 182, 0, 0, 19, 0, 0, 30, CT_GRAIN , 0 }, /* 33 */ - { 40, 2, 181, 0, 0, 16, 0, 0, 30, CT_WOOD , 0 }, /* 34 */ - { 41, 2, 179, 0, 0, 19, 0, 0, 30, CT_IRON_ORE , 0 }, /* 35 */ - { 42, 2, 196, 0, 0, 18, 0, 0, 20, CT_STEEL , 0 }, /* 36 */ - { 43, 2, 255, 0, 0, 30, 0, 0, 20, CT_VALUABLES , 0 }, /* 37 */ - { 44, 2, 191, 0, 0, 22, 0, 0, 25, CT_FOOD , 0 }, /* 38 */ - { 45, 2, 196, 0, 0, 18, 0, 0, 20, CT_PAPER , 0 }, /* 39 */ - { 46, 2, 179, 0, 0, 19, 0, 0, 30, CT_COPPER_ORE , 0 }, /* 40 */ - { 47, 2, 199, 0, 0, 25, 0, 0, 25, CT_WATER , 0 }, /* 41 */ - { 48, 2, 182, 0, 0, 18, 0, 0, 25, CT_FRUIT , 0 }, /* 42 */ - { 49, 2, 185, 0, 0, 19, 0, 0, 21, CT_RUBBER , 0 }, /* 43 */ - { 50, 2, 176, 0, 0, 19, 0, 0, 30, CT_SUGAR , 0 }, /* 44 */ - { 51, 2, 178, 0, 0, 20, 0, 0, 30, CT_COTTON_CANDY , 0 }, /* 45 */ - { 52, 2, 192, 0, 0, 20, 0, 0, 30, CT_TOFFEE , 0 }, /* 46 */ - { 53, 2, 190, 0, 0, 21, 0, 0, 20, CT_BUBBLES , 0 }, /* 47 */ - { 54, 2, 182, 0, 0, 24, 0, 0, 25, CT_COLA , 0 }, /* 48 */ - { 55, 2, 181, 0, 0, 21, 0, 0, 25, CT_CANDY , 0 }, /* 49 */ - { 56, 2, 183, 0, 0, 21, 0, 0, 20, CT_TOYS , 0 }, /* 50 */ - { 57, 2, 196, 0, 0, 18, 0, 0, 22, CT_BATTERIES , 0 }, /* 51 */ - { 58, 2, 193, 0, 0, 18, 0, 0, 25, CT_FIZZY_DRINKS , 0 }, /* 52 */ - { 59, 2, 191, 0, 0, 18, 0, 0, 30, CT_PLASTIC , 0 }, /* 53 */ - { 25, 0, 52, 304, 9000, 95, 230, 2, 0, 0 , 0 }, /* 54 */ - { 26, 1, 60, 336, 10000/2,85/2, 240/2, 2, 25, CT_PASSENGERS , 0 }, /* 55 */ - { 26, 0, 53, 320, 5000, 95, 230, 2, 0, 0 , 0 }, /* 56 */ - { 60, 2, 247, 0, 0, 25, 0, 0, 45, CT_PASSENGERS , 0 }, /* 57 */ - { 62, 2, 228, 0, 0, 21, 0, 0, 35, CT_MAIL , 0 }, /* 58 */ - { 61, 2, 176, 0, 0, 18, 0, 0, 35, CT_COAL , 0 }, /* 59 */ - { 63, 2, 200, 0, 0, 24, 0, 0, 35, CT_OIL , 0 }, /* 60 */ - { 64, 2, 192, 0, 0, 20, 0, 0, 30, CT_LIVESTOCK , 0 }, /* 61 */ - { 65, 2, 190, 0, 0, 21, 0, 0, 30, CT_GOODS , 0 }, /* 62 */ - { 66, 2, 182, 0, 0, 19, 0, 0, 35, CT_GRAIN , 0 }, /* 63 */ - { 67, 2, 181, 0, 0, 16, 0, 0, 35, CT_WOOD , 0 }, /* 64 */ - { 68, 2, 179, 0, 0, 19, 0, 0, 35, CT_IRON_ORE , 0 }, /* 65 */ - { 69, 2, 196, 0, 0, 18, 0, 0, 25, CT_STEEL , 0 }, /* 66 */ - { 70, 2, 255, 0, 0, 30, 0, 0, 25, CT_VALUABLES , 0 }, /* 67 */ - { 71, 2, 191, 0, 0, 22, 0, 0, 30, CT_FOOD , 0 }, /* 68 */ - { 72, 2, 196, 0, 0, 18, 0, 0, 25, CT_PAPER , 0 }, /* 69 */ - { 73, 2, 179, 0, 0, 19, 0, 0, 35, CT_COPPER_ORE , 0 }, /* 70 */ - { 47, 2, 199, 0, 0, 25, 0, 0, 30, CT_WATER , 0 }, /* 71 */ - { 48, 2, 182, 0, 0, 18, 0, 0, 30, CT_FRUIT , 0 }, /* 72 */ - { 49, 2, 185, 0, 0, 19, 0, 0, 26, CT_RUBBER , 0 }, /* 73 */ - { 50, 2, 176, 0, 0, 19, 0, 0, 35, CT_SUGAR , 0 }, /* 74 */ - { 51, 2, 178, 0, 0, 20, 0, 0, 35, CT_COTTON_CANDY , 0 }, /* 75 */ - { 52, 2, 192, 0, 0, 20, 0, 0, 35, CT_TOFFEE , 0 }, /* 76 */ - { 53, 2, 190, 0, 0, 21, 0, 0, 25, CT_BUBBLES , 0 }, /* 77 */ - { 54, 2, 182, 0, 0, 24, 0, 0, 30, CT_COLA , 0 }, /* 78 */ - { 55, 2, 181, 0, 0, 21, 0, 0, 30, CT_CANDY , 0 }, /* 79 */ - { 56, 2, 183, 0, 0, 21, 0, 0, 25, CT_TOYS , 0 }, /* 80 */ - { 57, 2, 196, 0, 0, 18, 0, 0, 27, CT_BATTERIES , 0 }, /* 81 */ - { 58, 2, 193, 0, 0, 18, 0, 0, 30, CT_FIZZY_DRINKS , 0 }, /* 82 */ - { 59, 2, 191, 0, 0, 18, 0, 0, 35, CT_PLASTIC , 0 }, /* 83 */ - { 28, 0, 70, 400, 10000, 105, 250, 2, 0, 0 , 0 }, /* 84 */ - { 29, 0, 74, 448, 12000, 120, 253, 2, 0, 0 , 0 }, /* 85 */ - { 30, 0, 82, 480, 15000, 130, 254, 2, 0, 0 , 0 }, /* 86 */ - { 31, 1, 95, 640, 20000/2,150/2,255/2, 2, 0, 0 , 0 }, /* 87 */ - { 28, 0, 70, 480, 10000, 120, 250, 2, 0, 0 , 0 }, /* 88 */ - { 60, 2, 247, 0, 0, 25, 0, 0, 47, CT_PASSENGERS , 0 }, /* 89 */ - { 62, 2, 228, 0, 0, 21, 0, 0, 37, CT_MAIL , 0 }, /* 90 */ - { 61, 2, 176, 0, 0, 18, 0, 0, 37, CT_COAL , 0 }, /* 91 */ - { 63, 2, 200, 0, 0, 24, 0, 0, 37, CT_OIL , 0 }, /* 92 */ - { 64, 2, 192, 0, 0, 20, 0, 0, 32, CT_LIVESTOCK , 0 }, /* 93 */ - { 65, 2, 190, 0, 0, 21, 0, 0, 32, CT_GOODS , 0 }, /* 94 */ - { 66, 2, 182, 0, 0, 19, 0, 0, 37, CT_GRAIN , 0 }, /* 95 */ - { 67, 2, 181, 0, 0, 16, 0, 0, 37, CT_WOOD , 0 }, /* 96 */ - { 68, 2, 179, 0, 0, 19, 0, 0, 37, CT_IRON_ORE , 0 }, /* 97 */ - { 69, 2, 196, 0, 0, 18, 0, 0, 27, CT_STEEL , 0 }, /* 98 */ - { 70, 2, 255, 0, 0, 30, 0, 0, 27, CT_VALUABLES , 0 }, /* 99 */ - { 71, 2, 191, 0, 0, 22, 0, 0, 32, CT_FOOD , 0 }, /* 100 */ - { 72, 2, 196, 0, 0, 18, 0, 0, 27, CT_PAPER , 0 }, /* 101 */ - { 73, 2, 179, 0, 0, 19, 0, 0, 37, CT_COPPER_ORE , 0 }, /* 102 */ - { 47, 2, 199, 0, 0, 25, 0, 0, 32, CT_WATER , 0 }, /* 103 */ - { 48, 2, 182, 0, 0, 18, 0, 0, 32, CT_FRUIT , 0 }, /* 104 */ - { 49, 2, 185, 0, 0, 19, 0, 0, 28, CT_RUBBER , 0 }, /* 105 */ - { 50, 2, 176, 0, 0, 19, 0, 0, 37, CT_SUGAR , 0 }, /* 106 */ - { 51, 2, 178, 0, 0, 20, 0, 0, 37, CT_COTTON_CANDY , 0 }, /* 107 */ - { 52, 2, 192, 0, 0, 20, 0, 0, 37, CT_TOFFEE , 0 }, /* 108 */ - { 53, 2, 190, 0, 0, 21, 0, 0, 27, CT_BUBBLES , 0 }, /* 109 */ - { 54, 2, 182, 0, 0, 24, 0, 0, 32, CT_COLA , 0 }, /* 110 */ - { 55, 2, 181, 0, 0, 21, 0, 0, 32, CT_CANDY , 0 }, /* 111 */ - { 56, 2, 183, 0, 0, 21, 0, 0, 27, CT_TOYS , 0 }, /* 112 */ - { 57, 2, 196, 0, 0, 18, 0, 0, 29, CT_BATTERIES , 0 }, /* 113 */ - { 58, 2, 193, 0, 0, 18, 0, 0, 32, CT_FIZZY_DRINKS , 0 }, /* 114 */ - { 59, 2, 191, 0, 0, 18, 0, 0, 37, CT_PLASTIC , 0 }, /* 115 */ + // | flags | power (hp) | running_cost_class | powered wagons power + // | | base_cost | weight | capacity | | powered wagons weight + // | | | | | | | | | cargo_type | | | visual effects + // | | | | | | | | | | | | | | + { 2, 0, 7, 64, 300, 47, 50, 0, 0, 0 , 0, 0, 0, 0 }, /* 0 */ + { 19, 0, 8, 80, 600, 65, 65, 1, 0, 0 , 0, 0, 0, 0 }, /* 1 */ + { 2, 0, 10, 72, 400, 85, 90, 0, 0, 0 , 0, 0, 0, 0 }, /* 2 */ + { 0, 0, 15, 96, 900, 130, 130, 0, 0, 0 , 0, 0, 0, 0 }, /* 3 */ + { 1, 0, 19, 112, 1000, 140, 145, 0, 0, 0 , 0, 0, 0, 0 }, /* 4 */ + { 12, 0, 16, 120, 1400, 95, 125, 1, 0, 0 , 0, 0, 0, 0 }, /* 5 */ + { 14, 0, 20, 152, 2000, 120, 135, 1, 0, 0 , 0, 0, 0, 0 }, /* 6 */ + { 3, 0, 14, 88, 1100, 145, 130, 0, 0, 0 , 0, 0, 0, 0 }, /* 7 */ + { 0, 0, 13, 112, 1000, 131, 120, 0, 0, 0 , 0, 0, 0, 0 }, /* 8 */ + { 1, 0, 19, 128, 1200, 162, 140, 0, 0, 0 , 0, 0, 0, 0 }, /* 9 */ + { 0, 0, 22, 144, 1600, 170, 130, 0, 0, 0 , 0, 0, 0, 0 }, /* 10 */ + { 8, 1, 11, 112, 600/2,32/2, 85/2, 1, 38, CT_PASSENGERS , 0, 0, 0, 0 }, /* 11 */ + { 10, 1, 14, 120, 700/2,38/2, 70/2, 1, 40, CT_PASSENGERS , 0, 0, 0, 0 }, /* 12 */ + { 4, 0, 15, 128, 1250, 72, 95, 1, 0, 0 , 0, 0, 0, 0 }, /* 13 */ + { 5, 0, 17, 144, 1750, 101, 120, 1, 0, 0 , 0, 0, 0, 0 }, /* 14 */ + { 4, 0, 18, 160, 2580, 112, 140, 1, 0, 0 , 0, 0, 0, 0 }, /* 15 */ + { 14, 0, 23, 96, 4000, 150, 135, 1, 0, 0 , 0, 0, 0, 0 }, /* 16 */ + { 12, 0, 16, 112, 2400, 120, 105, 1, 0, 0 , 0, 0, 0, 0 }, /* 17 */ + { 13, 0, 30, 112, 6600, 207, 155, 1, 0, 0 , 0, 0, 0, 0 }, /* 18 */ + { 15, 0, 18, 104, 1500, 110, 105, 1, 0, 0 , 0, 0, 0, 0 }, /* 19 */ + { 16, 1, 35, 160, 3500/2,95/2, 205/2, 1, 0, 0 , 0, 0, 0, 0 }, /* 20 */ + { 18, 0, 21, 104, 2200, 120, 145, 1, 0, 0 , 0, 0, 0, 0 }, /* 21 */ + { 6, 1, 20, 200, 4500/2,70/2, 190/2, 1, 4, CT_MAIL , 0, 0, 0, 0 }, /* 22 */ + { 20, 0, 26, 160, 3600, 84, 180, 2, 0, 0 , 0, 0, 0, 0 }, /* 23 */ + { 20, 0, 30, 176, 5000, 82, 205, 2, 0, 0 , 0, 0, 0, 0 }, /* 24 */ + { 21, 1, 40, 240, 7000/2,90/2, 240/2, 2, 0, 0 , 0, 0, 0, 0 }, /* 25 */ + { 23, 1, 43, 264, 8000/2,95/2, 250/2, 2, 0, 0 , 0, 0, 0, 0 }, /* 26 */ + { 33, 2, 247, 0, 0, 25, 0, 0, 40, CT_PASSENGERS , 0, 0, 0, 0 }, /* 27 */ + { 35, 2, 228, 0, 0, 21, 0, 0, 30, CT_MAIL , 0, 0, 0, 0 }, /* 28 */ + { 34, 2, 176, 0, 0, 18, 0, 0, 30, CT_COAL , 0, 0, 0, 0 }, /* 29 */ + { 36, 2, 200, 0, 0, 24, 0, 0, 30, CT_OIL , 0, 0, 0, 0 }, /* 30 */ + { 37, 2, 192, 0, 0, 20, 0, 0, 25, CT_LIVESTOCK , 0, 0, 0, 0 }, /* 31 */ + { 38, 2, 190, 0, 0, 21, 0, 0, 25, CT_GOODS , 0, 0, 0, 0 }, /* 32 */ + { 39, 2, 182, 0, 0, 19, 0, 0, 30, CT_GRAIN , 0, 0, 0, 0 }, /* 33 */ + { 40, 2, 181, 0, 0, 16, 0, 0, 30, CT_WOOD , 0, 0, 0, 0 }, /* 34 */ + { 41, 2, 179, 0, 0, 19, 0, 0, 30, CT_IRON_ORE , 0, 0, 0, 0 }, /* 35 */ + { 42, 2, 196, 0, 0, 18, 0, 0, 20, CT_STEEL , 0, 0, 0, 0 }, /* 36 */ + { 43, 2, 255, 0, 0, 30, 0, 0, 20, CT_VALUABLES , 0, 0, 0, 0 }, /* 37 */ + { 44, 2, 191, 0, 0, 22, 0, 0, 25, CT_FOOD , 0, 0, 0, 0 }, /* 38 */ + { 45, 2, 196, 0, 0, 18, 0, 0, 20, CT_PAPER , 0, 0, 0, 0 }, /* 39 */ + { 46, 2, 179, 0, 0, 19, 0, 0, 30, CT_COPPER_ORE , 0, 0, 0, 0 }, /* 40 */ + { 47, 2, 199, 0, 0, 25, 0, 0, 25, CT_WATER , 0, 0, 0, 0 }, /* 41 */ + { 48, 2, 182, 0, 0, 18, 0, 0, 25, CT_FRUIT , 0, 0, 0, 0 }, /* 42 */ + { 49, 2, 185, 0, 0, 19, 0, 0, 21, CT_RUBBER , 0, 0, 0, 0 }, /* 43 */ + { 50, 2, 176, 0, 0, 19, 0, 0, 30, CT_SUGAR , 0, 0, 0, 0 }, /* 44 */ + { 51, 2, 178, 0, 0, 20, 0, 0, 30, CT_COTTON_CANDY , 0, 0, 0, 0 }, /* 45 */ + { 52, 2, 192, 0, 0, 20, 0, 0, 30, CT_TOFFEE , 0, 0, 0, 0 }, /* 46 */ + { 53, 2, 190, 0, 0, 21, 0, 0, 20, CT_BUBBLES , 0, 0, 0, 0 }, /* 47 */ + { 54, 2, 182, 0, 0, 24, 0, 0, 25, CT_COLA , 0, 0, 0, 0 }, /* 48 */ + { 55, 2, 181, 0, 0, 21, 0, 0, 25, CT_CANDY , 0, 0, 0, 0 }, /* 49 */ + { 56, 2, 183, 0, 0, 21, 0, 0, 20, CT_TOYS , 0, 0, 0, 0 }, /* 50 */ + { 57, 2, 196, 0, 0, 18, 0, 0, 22, CT_BATTERIES , 0, 0, 0, 0 }, /* 51 */ + { 58, 2, 193, 0, 0, 18, 0, 0, 25, CT_FIZZY_DRINKS , 0, 0, 0, 0 }, /* 52 */ + { 59, 2, 191, 0, 0, 18, 0, 0, 30, CT_PLASTIC , 0, 0, 0, 0 }, /* 53 */ + { 25, 0, 52, 304, 9000, 95, 230, 2, 0, 0 , 0, 0, 0, 0 }, /* 54 */ + { 26, 1, 60, 336, 10000/2,85/2, 240/2, 2, 25, CT_PASSENGERS , 0, 0, 0, 0 }, /* 55 */ + { 26, 0, 53, 320, 5000, 95, 230, 2, 0, 0 , 0, 0, 0, 0 }, /* 56 */ + { 60, 2, 247, 0, 0, 25, 0, 0, 45, CT_PASSENGERS , 0, 0, 0, 0 }, /* 57 */ + { 62, 2, 228, 0, 0, 21, 0, 0, 35, CT_MAIL , 0, 0, 0, 0 }, /* 58 */ + { 61, 2, 176, 0, 0, 18, 0, 0, 35, CT_COAL , 0, 0, 0, 0 }, /* 59 */ + { 63, 2, 200, 0, 0, 24, 0, 0, 35, CT_OIL , 0, 0, 0, 0 }, /* 60 */ + { 64, 2, 192, 0, 0, 20, 0, 0, 30, CT_LIVESTOCK , 0, 0, 0, 0 }, /* 61 */ + { 65, 2, 190, 0, 0, 21, 0, 0, 30, CT_GOODS , 0, 0, 0, 0 }, /* 62 */ + { 66, 2, 182, 0, 0, 19, 0, 0, 35, CT_GRAIN , 0, 0, 0, 0 }, /* 63 */ + { 67, 2, 181, 0, 0, 16, 0, 0, 35, CT_WOOD , 0, 0, 0, 0 }, /* 64 */ + { 68, 2, 179, 0, 0, 19, 0, 0, 35, CT_IRON_ORE , 0, 0, 0, 0 }, /* 65 */ + { 69, 2, 196, 0, 0, 18, 0, 0, 25, CT_STEEL , 0, 0, 0, 0 }, /* 66 */ + { 70, 2, 255, 0, 0, 30, 0, 0, 25, CT_VALUABLES , 0, 0, 0, 0 }, /* 67 */ + { 71, 2, 191, 0, 0, 22, 0, 0, 30, CT_FOOD , 0, 0, 0, 0 }, /* 68 */ + { 72, 2, 196, 0, 0, 18, 0, 0, 25, CT_PAPER , 0, 0, 0, 0 }, /* 69 */ + { 73, 2, 179, 0, 0, 19, 0, 0, 35, CT_COPPER_ORE , 0, 0, 0, 0 }, /* 70 */ + { 47, 2, 199, 0, 0, 25, 0, 0, 30, CT_WATER , 0, 0, 0, 0 }, /* 71 */ + { 48, 2, 182, 0, 0, 18, 0, 0, 30, CT_FRUIT , 0, 0, 0, 0 }, /* 72 */ + { 49, 2, 185, 0, 0, 19, 0, 0, 26, CT_RUBBER , 0, 0, 0, 0 }, /* 73 */ + { 50, 2, 176, 0, 0, 19, 0, 0, 35, CT_SUGAR , 0, 0, 0, 0 }, /* 74 */ + { 51, 2, 178, 0, 0, 20, 0, 0, 35, CT_COTTON_CANDY , 0, 0, 0, 0 }, /* 75 */ + { 52, 2, 192, 0, 0, 20, 0, 0, 35, CT_TOFFEE , 0, 0, 0, 0 }, /* 76 */ + { 53, 2, 190, 0, 0, 21, 0, 0, 25, CT_BUBBLES , 0, 0, 0, 0 }, /* 77 */ + { 54, 2, 182, 0, 0, 24, 0, 0, 30, CT_COLA , 0, 0, 0, 0 }, /* 78 */ + { 55, 2, 181, 0, 0, 21, 0, 0, 30, CT_CANDY , 0, 0, 0, 0 }, /* 79 */ + { 56, 2, 183, 0, 0, 21, 0, 0, 25, CT_TOYS , 0, 0, 0, 0 }, /* 80 */ + { 57, 2, 196, 0, 0, 18, 0, 0, 27, CT_BATTERIES , 0, 0, 0, 0 }, /* 81 */ + { 58, 2, 193, 0, 0, 18, 0, 0, 30, CT_FIZZY_DRINKS , 0, 0, 0, 0 }, /* 82 */ + { 59, 2, 191, 0, 0, 18, 0, 0, 35, CT_PLASTIC , 0, 0, 0, 0 }, /* 83 */ + { 28, 0, 70, 400, 10000, 105, 250, 2, 0, 0 , 0, 0, 0, 0 }, /* 84 */ + { 29, 0, 74, 448, 12000, 120, 253, 2, 0, 0 , 0, 0, 0, 0 }, /* 85 */ + { 30, 0, 82, 480, 15000, 130, 254, 2, 0, 0 , 0, 0, 0, 0 }, /* 86 */ + { 31, 1, 95, 640, 20000/2,150/2,255/2, 2, 0, 0 , 0, 0, 0, 0 }, /* 87 */ + { 28, 0, 70, 480, 10000, 120, 250, 2, 0, 0 , 0, 0, 0, 0 }, /* 88 */ + { 60, 2, 247, 0, 0, 25, 0, 0, 47, CT_PASSENGERS , 0, 0, 0, 0 }, /* 89 */ + { 62, 2, 228, 0, 0, 21, 0, 0, 37, CT_MAIL , 0, 0, 0, 0 }, /* 90 */ + { 61, 2, 176, 0, 0, 18, 0, 0, 37, CT_COAL , 0, 0, 0, 0 }, /* 91 */ + { 63, 2, 200, 0, 0, 24, 0, 0, 37, CT_OIL , 0, 0, 0, 0 }, /* 92 */ + { 64, 2, 192, 0, 0, 20, 0, 0, 32, CT_LIVESTOCK , 0, 0, 0, 0 }, /* 93 */ + { 65, 2, 190, 0, 0, 21, 0, 0, 32, CT_GOODS , 0, 0, 0, 0 }, /* 94 */ + { 66, 2, 182, 0, 0, 19, 0, 0, 37, CT_GRAIN , 0, 0, 0, 0 }, /* 95 */ + { 67, 2, 181, 0, 0, 16, 0, 0, 37, CT_WOOD , 0, 0, 0, 0 }, /* 96 */ + { 68, 2, 179, 0, 0, 19, 0, 0, 37, CT_IRON_ORE , 0, 0, 0, 0 }, /* 97 */ + { 69, 2, 196, 0, 0, 18, 0, 0, 27, CT_STEEL , 0, 0, 0, 0 }, /* 98 */ + { 70, 2, 255, 0, 0, 30, 0, 0, 27, CT_VALUABLES , 0, 0, 0, 0 }, /* 99 */ + { 71, 2, 191, 0, 0, 22, 0, 0, 32, CT_FOOD , 0, 0, 0, 0 }, /* 100 */ + { 72, 2, 196, 0, 0, 18, 0, 0, 27, CT_PAPER , 0, 0, 0, 0 }, /* 101 */ + { 73, 2, 179, 0, 0, 19, 0, 0, 37, CT_COPPER_ORE , 0, 0, 0, 0 }, /* 102 */ + { 47, 2, 199, 0, 0, 25, 0, 0, 32, CT_WATER , 0, 0, 0, 0 }, /* 103 */ + { 48, 2, 182, 0, 0, 18, 0, 0, 32, CT_FRUIT , 0, 0, 0, 0 }, /* 104 */ + { 49, 2, 185, 0, 0, 19, 0, 0, 28, CT_RUBBER , 0, 0, 0, 0 }, /* 105 */ + { 50, 2, 176, 0, 0, 19, 0, 0, 37, CT_SUGAR , 0, 0, 0, 0 }, /* 106 */ + { 51, 2, 178, 0, 0, 20, 0, 0, 37, CT_COTTON_CANDY , 0, 0, 0, 0 }, /* 107 */ + { 52, 2, 192, 0, 0, 20, 0, 0, 37, CT_TOFFEE , 0, 0, 0, 0 }, /* 108 */ + { 53, 2, 190, 0, 0, 21, 0, 0, 27, CT_BUBBLES , 0, 0, 0, 0 }, /* 109 */ + { 54, 2, 182, 0, 0, 24, 0, 0, 32, CT_COLA , 0, 0, 0, 0 }, /* 110 */ + { 55, 2, 181, 0, 0, 21, 0, 0, 32, CT_CANDY , 0, 0, 0, 0 }, /* 111 */ + { 56, 2, 183, 0, 0, 21, 0, 0, 27, CT_TOYS , 0, 0, 0, 0 }, /* 112 */ + { 57, 2, 196, 0, 0, 18, 0, 0, 29, CT_BATTERIES , 0, 0, 0, 0 }, /* 113 */ + { 58, 2, 193, 0, 0, 18, 0, 0, 32, CT_FIZZY_DRINKS , 0, 0, 0, 0 }, /* 114 */ + { 59, 2, 191, 0, 0, 18, 0, 0, 37, CT_PLASTIC , 0, 0, 0, 0 }, /* 115 */ }; ShipVehicleInfo _ship_vehicle_info[NUM_SHIP_ENGINES] = { diff --git a/train_cmd.c b/train_cmd.c --- a/train_cmd.c +++ b/train_cmd.c @@ -41,9 +41,12 @@ void TrainCargoChanged(Vehicle *v) { const RailVehicleInfo *rvi = RailVehInfo(u->engine_type); uint16 vweight = 0; - // vehicle weight is the sum of the weight of the vehicle and the wait of its cargo + // vehicle weight is the sum of the weight of the vehicle and the weight of its cargo vweight += rvi->weight; vweight += (_cargoc.weights[u->cargo_type] * u->cargo_count) / 16; + // powered wagons have extra weight added + if HASBIT(u->u.rail.flags, VRF_POWEREDWAGON) + vweight += RailVehInfo(v->engine_type)->pow_wag_weight; // consist weight is the sum of the weight of all vehicles in the consist weight += vweight; @@ -62,27 +65,45 @@ void TrainCargoChanged(Vehicle *v) { * @param v First vehicle of the consist. */ void TrainConsistChanged(Vehicle *v) { + const RailVehicleInfo *rvi_v = RailVehInfo(v->engine_type); Vehicle *u; uint16 max_speed = 0xFFFF; uint32 power = 0; - // recalculate cached weights too - TrainCargoChanged(v); - for (u = v; u != NULL; u = u->next) { - const RailVehicleInfo *rvi = RailVehInfo(u->engine_type); - - // power is the sum of the powers of all engines in the consist - power += rvi->power; - - // max speed is the minimun of the speed limits of all vehicles in the consist - if (rvi->max_speed != 0) - max_speed = min(rvi->max_speed, max_speed); + const RailVehicleInfo *rvi_u = RailVehInfo(u->engine_type); + + // power is the sum of the powers of all engines and powered wagons in the consist + power += rvi_u->power; + + // check if its a powered wagon + CLRBIT(u->u.rail.flags, VRF_POWEREDWAGON); + if ((rvi_v->pow_wag_power != 0) && (rvi_u->flags & RVI_WAGON) && UsesWagonOverride(u)) { + uint16 callback; + + callback = GetCallBackResult(CBID_WAGON_POWER, u->engine_type, u); + + if (callback == CALLBACK_FAILED) + callback = rvi_u->visual_effect; + + if (callback < 0x40) { + /* wagon is powered */ + SETBIT(u->u.rail.flags, VRF_POWEREDWAGON); // cache 'powered' status + power += rvi_v->pow_wag_power; + } + } + + // max speed is the minimum of the speed limits of all vehicles in the consist + if (rvi_u->max_speed != 0) + max_speed = min(rvi_u->max_speed, max_speed); }; // store consist weight/max speed in cache v->u.rail.cached_max_speed = max_speed; v->u.rail.cached_power = power; + + // recalculate cached weights too (we do this *after* the rest, so it is known which wagons are powered and need extra weight added) + TrainCargoChanged(v); } /* These two arrays are used for realistic acceleration. XXX: How should they diff --git a/train_gui.c b/train_gui.c --- a/train_gui.c +++ b/train_gui.c @@ -47,6 +47,14 @@ void DrawTrainEnginePurchaseInfo(int x, DrawString(x,y, STR_PURCHASE_INFO_RUNNINGCOST, 0); y += 10; + /* Powered wagons power - Powered wagons extra weight */ + if (rvi->pow_wag_power != 0) { + SetDParam(0, rvi->pow_wag_power); + SetDParam(1, rvi->pow_wag_weight); + DrawString(x,y, STR_PURCHASE_INFO_PWAGPOWER_PWAGWEIGHT, 0); + y += 10; + }; + /* Cargo type + capacity, or N/A */ SetDParam(0, STR_8838_N_A); SetDParam(2, STR_EMPTY); @@ -280,15 +288,15 @@ static const Widget _new_rail_vehicle_wi { WWT_CAPTION, RESIZE_NONE, 14, 11, 227, 0, 13, STR_JUST_STRING, STR_018C_WINDOW_TITLE_DRAG_THIS}, { WWT_MATRIX, RESIZE_BOTTOM, 14, 0, 215, 14, 125, 0x801, STR_8843_TRAIN_VEHICLE_SELECTION}, { WWT_SCROLLBAR, RESIZE_BOTTOM, 14, 216, 227, 14, 125, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, -{ WWT_PANEL, RESIZE_TB, 14, 0, 227, 126, 187, 0x0, STR_NULL}, -{ WWT_PUSHTXTBTN, RESIZE_TB, 14, 0, 107, 188, 199, STR_881F_BUILD_VEHICLE, STR_8844_BUILD_THE_HIGHLIGHTED_TRAIN}, -{ WWT_PUSHTXTBTN, RESIZE_TB, 14, 108, 215, 188, 199, STR_8820_RENAME, STR_8845_RENAME_TRAIN_VEHICLE_TYPE}, -{ WWT_RESIZEBOX, RESIZE_TB, 14, 216, 227, 188, 199, 0x0, STR_RESIZE_BUTTON}, +{ WWT_PANEL, RESIZE_TB, 14, 0, 227, 126, 197, 0x0, STR_NULL}, +{ WWT_PUSHTXTBTN, RESIZE_TB, 14, 0, 107, 198, 209, STR_881F_BUILD_VEHICLE, STR_8844_BUILD_THE_HIGHLIGHTED_TRAIN}, +{ WWT_PUSHTXTBTN, RESIZE_TB, 14, 108, 215, 198, 209, STR_8820_RENAME, STR_8845_RENAME_TRAIN_VEHICLE_TYPE}, +{ WWT_RESIZEBOX, RESIZE_TB, 14, 216, 227, 198, 209, 0x0, STR_RESIZE_BUTTON}, { WIDGETS_END}, }; static const WindowDesc _new_rail_vehicle_desc = { - -1, -1, 228, 200, + -1, -1, 228, 210, WC_BUILD_VEHICLE,0, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_RESIZABLE, _new_rail_vehicle_widgets, diff --git a/vehicle.h b/vehicle.h --- a/vehicle.h +++ b/vehicle.h @@ -74,6 +74,9 @@ enum { // used to calculate if train is going up or down VRF_GOINGUP = 1, VRF_GOINGDOWN = 2, + + // used to store if a wagon is powered or not + VRF_POWEREDWAGON = 3, }; typedef struct VehicleAir {