diff options
author | peter1138 <peter1138@openttd.org> | 2005-11-06 13:42:26 +0000 |
---|---|---|
committer | peter1138 <peter1138@openttd.org> | 2005-11-06 13:42:26 +0000 |
commit | bc25cd89bffd79785957b3f91f78c6646e9a51a6 (patch) | |
tree | 84353e1ac91e579a3ea163316e9e1fe281200d11 | |
parent | 220b4c27c1f8f58740ae4195e71f5e582a8474d0 (diff) | |
download | openttd-bc25cd89bffd79785957b3f91f78c6646e9a51a6.tar.xz |
(svn r3148) -NewGRF, Feature: Add support for cargo refitting specification by cargo classes.
-rw-r--r-- | engine.c | 22 | ||||
-rw-r--r-- | engine.h | 3 | ||||
-rw-r--r-- | newgrf.c | 89 | ||||
-rw-r--r-- | table/engines.h | 4 | ||||
-rw-r--r-- | train_gui.c | 4 | ||||
-rw-r--r-- | vehicle.c | 13 | ||||
-rw-r--r-- | vehicle_gui.c | 10 |
7 files changed, 110 insertions, 35 deletions
@@ -58,10 +58,10 @@ const CargoID _local_cargo_id_ctype[NUM_GLOBAL_CID] = { const uint32 _landscape_global_cargo_mask[NUM_LANDSCAPE] = { /* LT_NORMAL: temperate */ MC(GC_PASSENGERS)|MC(GC_COAL)|MC(GC_MAIL)|MC(GC_OIL)|MC(GC_LIVESTOCK)|MC(GC_GOODS)|MC(GC_GRAIN)|MC(GC_WOOD)| - MC(GC_IRON_ORE)|MC(GC_STEEL)|MC(GC_VALUABLES)|MC(GC_FOOD)|MC(GC_UNDEFINED), + MC(GC_IRON_ORE)|MC(GC_STEEL)|MC(GC_VALUABLES), /* LT_HILLY: arctic */ MC(GC_PASSENGERS)|MC(GC_COAL)|MC(GC_MAIL)|MC(GC_OIL)|MC(GC_LIVESTOCK)|MC(GC_GOODS)| - MC(GC_GRAIN)|MC(GC_WOOD)|MC(GC_VALUABLES)|MC(GC_PAPER)|MC(GC_FOOD)|MC(GC_UNDEFINED), + MC(GC_GRAIN)|MC(GC_WOOD)|MC(GC_VALUABLES)|MC(GC_PAPER)|MC(GC_FOOD), /* LT_DESERT: rainforest/desert */ MC(GC_PASSENGERS)|MC(GC_MAIL)|MC(GC_OIL)|MC(GC_GOODS)|MC(GC_GRAIN)|MC(GC_WOOD)| MC(GC_VALUABLES)|MC(GC_FOOD)|MC(GC_FRUIT)|MC(GC_COPPER_ORE)|MC(GC_WATER)|MC(GC_RUBBER), @@ -91,6 +91,21 @@ const uint32 _default_refitmasks[NUM_VEHICLE_TYPES] = { /* Special/Disaster */ 0,0 }; + +/** + * Bitmask of classes for cargo types. + */ +const uint32 cargo_classes[16] = { + /* Passengers */ MC(GC_PASSENGERS), + /* Mail */ MC(GC_MAIL), + /* Express */ MC(GC_GOODS)|MC(GC_FOOD)|MC(GC_CANDY), + /* Armoured */ MC(GC_VALUABLES), + /* Bulk */ MC(GC_COAL)|MC(GC_GRAIN)|MC(GC_IRON_ORE)|MC(GC_COPPER_ORE)|MC(GC_FRUIT)|MC(GC_SUGAR)|MC(GC_TOFFEE)|MC(GC_COTTON_CANDY), + /* Piece */ MC(GC_LIVESTOCK)|MC(GC_WOOD)|MC(GC_STEEL)|MC(GC_PAPER)|MC(GC_TOYS)|MC(GC_BATTERIES)|MC(GC_BUBBLES)|MC(GC_FIZZY_DRINKS), + /* Liquids */ MC(GC_OIL)|MC(GC_WATER)|MC(GC_RUBBER)|MC(GC_COLA)|MC(GC_PLASTIC), + /* Chilled */ MC(GC_FOOD)|MC(GC_FRUIT), + /* Undefined */ 0, 0, 0, 0, 0, 0, 0, 0 +}; #undef MC void ShowEnginePreviewWindow(EngineID engine); @@ -232,9 +247,6 @@ void StartupEngines(void) AdjustAvailAircraft(); } -uint32 _engine_refit_masks[TOTAL_NUM_ENGINES]; - - // TODO: We don't support cargo-specific wagon overrides. Pretty exotic... ;-) --pasky typedef struct WagonOverride { @@ -72,6 +72,7 @@ typedef struct EngineInfo { byte base_life; byte railtype:4; byte climates:4; + uint32 refit_mask; } EngineInfo; typedef struct Engine { @@ -174,8 +175,8 @@ VARDEF const uint32 _default_refitmasks[NUM_VEHICLE_TYPES]; VARDEF const CargoID _global_cargo_id[NUM_LANDSCAPE][NUM_CARGO]; VARDEF const uint32 _landscape_global_cargo_mask[NUM_LANDSCAPE]; VARDEF const CargoID _local_cargo_id_ctype[NUM_GLOBAL_CID]; +VARDEF const uint32 cargo_classes[16]; -VARDEF uint32 _engine_refit_masks[256]; void SetWagonOverrideSprites(EngineID engine, struct SpriteGroup *group, byte *train_id, int trains); void SetCustomEngineSprites(EngineID engine, byte cargo, struct SpriteGroup *group); // loaded is in percents, overriding_engine 0xffff is none @@ -72,6 +72,8 @@ static const int _vehshifts[4] = { /* GSF_AIRCRAFT */ AIRCRAFT_ENGINES_INDEX, }; +static uint16 cargo_allowed[TOTAL_NUM_ENGINES]; +static uint16 cargo_disallowed[TOTAL_NUM_ENGINES]; /* Debugging messages policy: * @@ -352,7 +354,7 @@ static bool RailVehicleChangeInfo(uint engine, int numinfo, int prop, byte **buf FOR_EACH_OBJECT { uint32 refit_mask = grf_load_dword(&buf); - _engine_refit_masks[engine + i] = refit_mask; + _engine_info[engine + i].refit_mask = refit_mask; } } break; case 0x1E: { /* Callback */ @@ -395,6 +397,16 @@ static bool RailVehicleChangeInfo(uint engine, int numinfo, int prop, byte **buf } } } break; + case 0x28: { /* Cargo classes allowed */ + FOR_EACH_OBJECT { + cargo_allowed[engine + i] = grf_load_word(&buf); + } + } break; + case 0x29: { /* Cargo classes disallowed */ + FOR_EACH_OBJECT { + cargo_disallowed[engine + i] = grf_load_word(&buf); + } + } break; /* TODO */ /* Fall-through for unimplemented one byte long properties. */ case 0x1A: /* Sort order */ @@ -499,7 +511,17 @@ static bool RoadVehicleChangeInfo(uint engine, int numinfo, int prop, byte **buf FOR_EACH_OBJECT { uint32 refit_mask = grf_load_dword(&buf); - _engine_refit_masks[ROAD_ENGINES_INDEX + engine + i] = refit_mask; + _engine_info[ROAD_ENGINES_INDEX + engine + i].refit_mask = refit_mask; + } + } break; + case 0x1D: { /* Cargo classes allowed */ + FOR_EACH_OBJECT { + cargo_allowed[ROAD_ENGINES_INDEX + engine + i] = grf_load_word(&buf); + } + } break; + case 0x1E: { /* Cargo classes disallowed */ + FOR_EACH_OBJECT { + cargo_disallowed[ROAD_ENGINES_INDEX + engine + i] = grf_load_word(&buf); } } break; case 0x17: /* Callback */ @@ -507,6 +529,7 @@ static bool RoadVehicleChangeInfo(uint engine, int numinfo, int prop, byte **buf case 0x19: /* Air drag */ case 0x1A: /* Refit cost */ case 0x1B: /* Retire vehicle early */ + case 0x1C: /* Miscellaneous flags */ { /* TODO */ FOR_EACH_OBJECT { @@ -602,14 +625,25 @@ static bool ShipVehicleChangeInfo(uint engine, int numinfo, int prop, byte **buf FOR_EACH_OBJECT { uint32 refit_mask = grf_load_dword(&buf); - _engine_refit_masks[SHIP_ENGINES_INDEX + engine + i] = refit_mask; + _engine_info[SHIP_ENGINES_INDEX + engine + i].refit_mask = refit_mask; } } break; + case 0x18: { /* Cargo classes allowed */ + FOR_EACH_OBJECT { + cargo_allowed[SHIP_ENGINES_INDEX + engine + i] = grf_load_word(&buf); + } + } break; + case 0x19: { /* Cargo classes disallowed */ + FOR_EACH_OBJECT { + cargo_disallowed[SHIP_ENGINES_INDEX + engine + i] = grf_load_word(&buf); + } + } break; case 0x12: /* Callback */ case 0x13: /* Refit cost */ case 0x14: /* Ocean speed fraction */ case 0x15: /* Canal speed fraction */ case 0x16: /* Retire vehicle early */ + case 0x17: /* Miscellaneous flags */ { /* TODO */ FOR_EACH_OBJECT { @@ -711,12 +745,23 @@ static bool AircraftVehicleChangeInfo(uint engine, int numinfo, int prop, byte * FOR_EACH_OBJECT { uint32 refit_mask = grf_load_dword(&buf); - _engine_refit_masks[AIRCRAFT_ENGINES_INDEX + engine + i] = refit_mask; + _engine_info[AIRCRAFT_ENGINES_INDEX + engine + i].refit_mask = refit_mask; } } break; + case 0x18: { /* Cargo classes allowed */ + FOR_EACH_OBJECT { + cargo_allowed[AIRCRAFT_ENGINES_INDEX + engine + i] = grf_load_word(&buf); + } + } break; + case 0x19: { /* Cargo classes disallowed */ + FOR_EACH_OBJECT { + cargo_disallowed[AIRCRAFT_ENGINES_INDEX + engine + i] = grf_load_word(&buf); + } + } break; case 0x14: /* Callback */ case 0x15: /* Refit cost */ case 0x16: /* Retire vehicle early */ + case 0x17: /* Miscellaneous flags */ { /* TODO */ FOR_EACH_OBJECT { @@ -2375,6 +2420,10 @@ static void ResetNewGRFData(void) } memcpy(&_bridge, &orig_bridge, sizeof(_bridge)); + // Reset refit/cargo class data + memset(&cargo_allowed, 0, sizeof(cargo_allowed)); + memset(&cargo_disallowed, 0, sizeof(cargo_disallowed)); + // Unload sprite group data UnloadWagonOverrides(); UnloadCustomEngineSprites(); @@ -2412,6 +2461,35 @@ static void InitNewGRFFile(const char* filename, int sprite_offset) } } +/** + * Precalculate refit masks from cargo classes for all vehicles. + */ +static void CalculateRefitMasks(void) +{ + EngineID engine; + + for (engine = 0; engine < TOTAL_NUM_ENGINES; engine++) { + uint32 mask = 0; + uint32 not_mask = 0; + uint32 xor_mask = _engine_info[engine].refit_mask; + byte i; + + if (cargo_allowed[engine] != 0) { + // Build up the list of cargo types from the set cargo classes. + for (i = 0; i < lengthof(cargo_classes); i++) { + if (HASBIT(cargo_allowed[engine], i)) + mask |= cargo_classes[i]; + if (HASBIT(cargo_disallowed[engine], i)) + not_mask |= cargo_classes[i]; + } + } else { + // Don't apply default refit mask to wagons or engines with no capacity + if (xor_mask == 0 && !(GetEngine(engine)->type == VEH_Train && (RailVehInfo(engine)->capacity == 0 || RailVehInfo(engine)->flags & RVI_WAGON))) + xor_mask = _default_refitmasks[GetEngine(engine)->type - VEH_Train]; + } + _engine_info[engine].refit_mask = ((mask & ~not_mask) ^ xor_mask) & _landscape_global_cargo_mask[_opt.landscape]; + } +} /* Here we perform initial decoding of some special sprites (as are they * described at http://www.ttdpatch.net/src/newgrf.txt, but this is only a very @@ -2593,4 +2671,7 @@ void LoadNewGRF(uint load_index, uint file_index) DEBUG(spritecache, 2) ("Currently %i sprites are loaded", load_index); } } + + // Pre-calculate all refit masks after loading GRF files + CalculateRefitMasks(); } diff --git a/table/engines.h b/table/engines.h index bba258287..b1ace97c6 100644 --- a/table/engines.h +++ b/table/engines.h @@ -15,7 +15,7 @@ * @param e Rail Type of the vehicle * @param f Bitmask of the climates */ -#define MK(a, b, c, d, e, f) { a, b, c, d, e, f } +#define MK(a, b, c, d, e, f) { a, b, c, d, e, f, 0 } /** Writes the properties of a train carriage into the EngineInfo struct. * @see EngineInfo * @param a Introduction date @@ -23,7 +23,7 @@ * @param f Bitmask of the climates * @note the 0x80 in parameter b sets the "is carriage bit" */ -#define MW(a, b, c, d, e, f) { a, b | 0x80, c, d, e, f } +#define MW(a, b, c, d, e, f) { a, b | 0x80, c, d, e, f, 0 } // Rail types // R = Conventional railway diff --git a/train_gui.c b/train_gui.c index ea347f2b2..5f925a8cb 100644 --- a/train_gui.c +++ b/train_gui.c @@ -90,7 +90,7 @@ void DrawTrainEnginePurchaseInfo(int x, int y, EngineID engine_number) void DrawTrainWagonPurchaseInfo(int x, int y, EngineID engine_number) { const RailVehicleInfo *rvi = RailVehInfo(engine_number); - bool refittable = (_engine_refit_masks[engine_number] != 0); + bool refittable = (_engine_info[engine_number].refit_mask != 0); /* Purchase cost */ SetDParam(0, (rvi->base_cost * _price.build_railwagon) >> 8); @@ -915,7 +915,7 @@ static void TrainViewWndProc(Window *w, WindowEvent *e) /* See if any vehicle can be refitted */ for ( u = v; u != NULL; u = u->next) { - if (_engine_refit_masks[u->engine_type] != 0 || + if (_engine_info[u->engine_type].refit_mask != 0 || (!(RailVehInfo(v->engine_type)->flags & RVI_WAGON) && v->cargo_cap != 0)) { CLRBIT(w->disabled_state, 12); /* We have a refittable carriage, bail out */ @@ -689,18 +689,7 @@ bool CanFillVehicle(Vehicle *v) bool CanRefitTo(const Vehicle *v, CargoID cid_to) { CargoID cid = _global_cargo_id[_opt_ptr->landscape][cid_to]; - - if (cid == GC_INVALID) return false; - - if (_engine_refit_masks[v->engine_type]) { - if (!HASBIT(_engine_refit_masks[v->engine_type], cid)) return false; - } else { - /* If we are talking about normal vehicles (no newgrf), you can only refit engines */ - if (v->type == VEH_Train && (RailVehInfo(v->engine_type)->flags & RVI_WAGON)) return false; - if (!HASBIT(_default_refitmasks[v->type - VEH_Train], cid)) return false; - } - - return true; + return HASBIT(_engine_info[v->engine_type].refit_mask, cid) != 0; } static void DoDrawVehicle(const Vehicle *v) diff --git a/vehicle_gui.c b/vehicle_gui.c index 818fb84aa..9edb40caa 100644 --- a/vehicle_gui.c +++ b/vehicle_gui.c @@ -226,18 +226,10 @@ CargoID DrawVehicleRefitWindow(const Vehicle *v, int sel) cmask = 0; u = v; do { - if (_engine_refit_masks[u->engine_type] != 0) { // newgrf custom refit mask - cmask |= _engine_refit_masks[u->engine_type]; - } else if (u->cargo_cap != 0) { - // rail wagons cant be refitted by default - if (v->type != VEH_Train || !(RailVehInfo(u->engine_type)->flags & RVI_WAGON)) - cmask |= _default_refitmasks[v->type - VEH_Train]; - } + cmask |= _engine_info[u->engine_type].refit_mask; u = u->next; } while (v->type == VEH_Train && u != NULL); - cmask &= _landscape_global_cargo_mask[_opt_ptr->landscape]; - /* Check which cargo has been selected from the refit window and draw list */ for (cid = 0; cmask != 0; cmask >>= 1, cid++) { if (HASBIT(cmask, 0)) // vehicle is refittable to this cargo |