diff --git a/src/newgrf.cpp b/src/newgrf.cpp index dae87a9222..baed23f6f4 100644 --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -479,6 +479,17 @@ static ChangeInfoResult RailVehicleChangeInfo(uint engine, int numinfo, int prop case 0x05: { // Track type uint8 tracktype = grf_load_byte(&buf); + if (tracktype < _cur_grffile->railtype_max) { + RailType railtype = GetRailTypeByLabel(_cur_grffile->railtype_list[tracktype]); + if (railtype == INVALID_RAILTYPE) { + /* Rail type is not available, so disable this engine */ + ei[i].climates = 0x80; + } else { + rvi[i].railtype = railtype; + } + break; + } + switch (tracktype) { case 0: rvi->railtype = rvi->engclass >= 2 ? RAILTYPE_ELECTRIC : RAILTYPE_RAIL; break; case 1: rvi->railtype = RAILTYPE_MONO; break; @@ -610,8 +621,13 @@ static ChangeInfoResult RailVehicleChangeInfo(uint engine, int numinfo, int prop } else { break; } - if (rvi->railtype == RAILTYPE_RAIL && engclass >= EC_ELECTRIC) rvi->railtype = RAILTYPE_ELECTRIC; - if (rvi->railtype == RAILTYPE_ELECTRIC && engclass < EC_ELECTRIC) rvi->railtype = RAILTYPE_RAIL; + + if (_cur_grffile->railtype_max == 0) { + /* Use traction type to select between normal and electrified + * rail only when no translation list is in place. */ + if (rvi->railtype == RAILTYPE_RAIL && engclass >= EC_ELECTRIC) rvi->railtype = RAILTYPE_ELECTRIC; + if (rvi->railtype == RAILTYPE_ELECTRIC && engclass < EC_ELECTRIC) rvi->railtype = RAILTYPE_RAIL; + } rvi->engclass = engclass; } break; @@ -1749,6 +1765,12 @@ static ChangeInfoResult GlobalVarChangeInfo(uint gvid, int numinfo, int prop, by buf += 8; break; + case 0x12: // Rail type translation table + /* This is loaded during the reservation stage, so just skip it here. */ + /* Each entry is 4 bytes. */ + buf += 4; + break; + default: ret = CIR_UNKNOWN; break; @@ -1810,6 +1832,23 @@ static ChangeInfoResult GlobalVarReserveInfo(uint gvid, int numinfo, int prop, b break; } + case 0x12: { // Rail type translation table + if (i == 0) { + if (gvid != 0) { + grfmsg(1, "ReserveChangeInfo: Rail type translation table must start at zero"); + return CIR_INVALID_ID; + } + + free(_cur_grffile->railtype_list); + _cur_grffile->railtype_max = numinfo; + _cur_grffile->railtype_list = MallocT(numinfo); + } + + RailTypeLabel rtl = grf_load_dword(&buf); + _cur_grffile->railtype_list[i] = BSWAP32(rtl); + break; + } + default: ret = CIR_UNKNOWN; break; diff --git a/src/newgrf.h b/src/newgrf.h index 83690e0039..172de0d5f0 100644 --- a/src/newgrf.h +++ b/src/newgrf.h @@ -10,6 +10,7 @@ #include "cargotype.h" #include "industry_type.h" #include "station_type.h" +#include "rail_type.h" enum GrfLoadingStage { GLS_FILESCAN, @@ -98,6 +99,9 @@ struct GRFFile { uint8 cargo_max; CargoLabel *cargo_list; uint8 cargo_map[NUM_CARGO]; + + uint8 railtype_max; + RailTypeLabel *railtype_list; }; extern GRFFile *_first_grffile; diff --git a/src/rail.cpp b/src/rail.cpp index ddc7162068..aa5ade657d 100644 --- a/src/rail.cpp +++ b/src/rail.cpp @@ -207,3 +207,15 @@ RailTypes GetCompanyRailtypes(CompanyID company) return rt; } + +RailType GetRailTypeByLabel(RailTypeLabel label) +{ + /* Loop through each rail type until the label is found */ + for (RailType r = RAILTYPE_BEGIN; r != RAILTYPE_END; r++) { + const RailtypeInfo *rti = GetRailTypeInfo(r); + if (rti->label == label) return r; + } + + /* No matching label was found, so it is invalid */ + return INVALID_RAILTYPE; +} diff --git a/src/rail.h b/src/rail.h index a787165ad8..5a9236597b 100644 --- a/src/rail.h +++ b/src/rail.h @@ -132,6 +132,11 @@ struct RailtypeInfo { * Cost multiplier for building this rail type */ uint8 cost_multiplier; + + /** + * Unique 32 bit rail type identifier + */ + RailTypeLabel label; }; @@ -254,6 +259,13 @@ RailType GetBestRailtype(const CompanyID company); */ RailTypes GetCompanyRailtypes(const CompanyID c); +/** + * Get the rail type for a given label. + * @param label the railtype label. + * @return the railtype. + */ +RailType GetRailTypeByLabel(RailTypeLabel label); + /** * Reset all rail type information to its default values. */ diff --git a/src/rail_type.h b/src/rail_type.h index 73876bd4af..e4cf3905d0 100644 --- a/src/rail_type.h +++ b/src/rail_type.h @@ -7,6 +7,8 @@ #include "core/enum_type.hpp" +typedef uint32 RailTypeLabel; + /** * Enumeration for all possible railtypes. * diff --git a/src/table/railtypes.h b/src/table/railtypes.h index 037014541a..b1082689c2 100644 --- a/src/table/railtypes.h +++ b/src/table/railtypes.h @@ -73,6 +73,9 @@ static const RailtypeInfo _original_railtypes[] = { /* cost multiplier */ 8, + + /* rail type label */ + 'RAIL', }, /** Electrified railway */ @@ -142,6 +145,9 @@ static const RailtypeInfo _original_railtypes[] = { /* cost multiplier */ 12, + + /* rail type label */ + 'ELRL', }, /** Monorail */ @@ -207,6 +213,9 @@ static const RailtypeInfo _original_railtypes[] = { /* cost multiplier */ 16, + + /* rail type label */ + 'MONO', }, /** Maglev */ @@ -272,6 +281,9 @@ static const RailtypeInfo _original_railtypes[] = { /* cost multiplier */ 24, + + /* rail type label */ + 'MGLV', }, };