summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--aircraft_cmd.c38
-rw-r--r--aircraft_gui.c126
-rw-r--r--command.c6
-rw-r--r--engine.c95
-rw-r--r--engine.h53
-rw-r--r--lang/english.txt1
-rw-r--r--newgrf.c5
-rw-r--r--ship_cmd.c39
-rw-r--r--ship_gui.c85
-rw-r--r--station.h2
-rw-r--r--train_cmd.c36
-rw-r--r--train_gui.c88
-rw-r--r--ttd.h1
-rw-r--r--vehicle.c22
-rw-r--r--vehicle.h1
-rw-r--r--vehicle_gui.c36
-rw-r--r--vehicle_gui.h1
17 files changed, 291 insertions, 344 deletions
diff --git a/aircraft_cmd.c b/aircraft_cmd.c
index b351fca6f..691005349 100644
--- a/aircraft_cmd.c
+++ b/aircraft_cmd.c
@@ -504,32 +504,38 @@ int32 CmdChangeAircraftServiceInt(int x, int y, uint32 flags, uint32 p1, uint32
return 0;
}
-// p1 = vehicle
-// p2 = new cargo type(0xFF)
-// p2 = skip check for stopped in hanger (0x0100)
+/** Refits an aircraft to the specified cargo type.
+ * @param x,y unused
+ * @param p1 vehicle ID of the aircraft to refit
+ * @param p2 various bitstuffed elements
+ * - p2 = (bit 0-7) - the new cargo type to refit to (p2 & 0xFF)
+ * - p2 = (bit 8) - skip check for stopped in hangar, used by autoreplace (p2 & 0x100)
+ * @todo p2 bit8 check <b>NEEDS TO GO</b>
+ */
int32 CmdRefitAircraft(int x, int y, uint32 flags, uint32 p1, uint32 p2)
{
- Vehicle *v,*u;
+ Vehicle *v;
int pass, mail;
int32 cost;
- byte SkipStoppedInHangerCheck = (p2 & 0x100) >> 8; //excludes the cargo value
- byte new_cargo_type = p2 & 0xFF; //gets the cargo number
- AircraftVehicleInfo *avi;
+ bool SkipStoppedInHangerCheck = !!HASBIT(p2, 8); // XXX - needs to go, yes?
+ CargoID new_cid = p2 & 0xFF; //gets the cargo number
+ const AircraftVehicleInfo *avi;
if (!IsVehicleIndex(p1)) return CMD_ERROR;
v = GetVehicle(p1);
- if (v->type != VEH_Aircraft) return CMD_ERROR;
+ if (v->type != VEH_Aircraft || !CheckOwnership(v->owner)) return CMD_ERROR;
+ if (!SkipStoppedInHangerCheck && !CheckStoppedInHangar(v)) return_cmd_error(STR_A01B_AIRCRAFT_MUST_BE_STOPPED);
avi = AircraftVehInfo(v->engine_type);
- if (!CheckOwnership(v->owner) || (!CheckStoppedInHangar(v) && !(SkipStoppedInHangerCheck)))
- return CMD_ERROR;
+ /* Check cargo */
+ if (new_cid > NUM_CARGO || !CanRefitTo(v, new_cid)) return CMD_ERROR;
SET_EXPENSES_TYPE(EXPENSES_AIRCRAFT_RUN);
- switch (new_cargo_type) {
+ switch (new_cid) {
case CT_PASSENGERS:
pass = avi->passenger_capacity;
break;
@@ -548,24 +554,22 @@ int32 CmdRefitAircraft(int x, int y, uint32 flags, uint32 p1, uint32 p2)
_aircraft_refit_capacity = pass;
cost = 0;
- if (IS_HUMAN_PLAYER(v->owner) && new_cargo_type != v->cargo_type) {
+ if (IS_HUMAN_PLAYER(v->owner) && new_cid != v->cargo_type) {
cost = _price.aircraft_base >> 7;
}
if (flags & DC_EXEC) {
+ Vehicle *u;
v->cargo_cap = pass;
u = v->next;
- mail = avi->mail_capacity;
- if (new_cargo_type != CT_PASSENGERS) {
- mail = 0;
- }
+ mail = (new_cid != CT_PASSENGERS) ? 0 : avi->mail_capacity;
u->cargo_cap = mail;
//autorefitted planes wants to keep the cargo
//it will be checked if the cargo is valid in CmdReplaceVehicle
if (!(SkipStoppedInHangerCheck))
v->cargo_count = u->cargo_count = 0;
- v->cargo_type = new_cargo_type;
+ v->cargo_type = new_cid;
InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
}
diff --git a/aircraft_gui.c b/aircraft_gui.c
index 60502ad33..a263813be 100644
--- a/aircraft_gui.c
+++ b/aircraft_gui.c
@@ -205,64 +205,11 @@ static void ShowBuildAircraftWindow(uint tile)
}
}
-#define MAX_REFIT 0xFF
-
-const byte _aircraft_refit_normal[] = {
- CT_PASSENGERS,
- CT_MAIL,
- CT_GOODS,
- CT_VALUABLES,
- MAX_REFIT
-};
-
-const byte _aircraft_refit_arctic[] = {
- CT_PASSENGERS,
- CT_MAIL,
- CT_GOODS,
- CT_FOOD,
- MAX_REFIT
-};
-
-const byte _aircraft_refit_desert[] = {
- CT_PASSENGERS,
- CT_MAIL,
- CT_FRUIT,
- CT_GOODS,
- CT_DIAMONDS,
- MAX_REFIT
-};
-
-const byte _aircraft_refit_candy[] = {
- CT_PASSENGERS,
- CT_SUGAR,
- CT_TOYS,
- CT_CANDY,
- CT_COLA,
- CT_COTTON_CANDY,
- CT_BUBBLES,
- CT_TOFFEE,
- CT_BATTERIES,
- CT_PLASTIC,
- CT_FIZZY_DRINKS,
- MAX_REFIT
-};
-
-const byte * const _aircraft_refit_types[4] = {
- _aircraft_refit_normal, _aircraft_refit_arctic, _aircraft_refit_desert, _aircraft_refit_candy
-};
-
-#undef MAX_REFIT
-
static void AircraftRefitWndProc(Window *w, WindowEvent *e)
{
- switch(e->event) {
+ switch (e->event) {
case WE_PAINT: {
- Vehicle *v = GetVehicle(w->window_number);
- const byte *b;
- int sel;
- int x,y;
- byte color;
- int cargo;
+ const Vehicle *v = GetVehicle(w->window_number);
SetDParam(0, v->string_id);
SetDParam(1, v->unitnumber);
@@ -271,72 +218,31 @@ static void AircraftRefitWndProc(Window *w, WindowEvent *e)
DrawString(1, 15, STR_A040_SELECT_CARGO_TYPE_TO_CARRY, 0);
/* TODO: Support for custom GRFSpecial-specified refitting! --pasky */
+ WP(w,refit_d).cargo = DrawVehicleRefitWindow(v, WP(w, refit_d).sel);
- cargo = -1;
- x = 6;
- y = 25;
- sel = WP(w,refit_d).sel;
-
-#define show_cargo(ctype) { \
- color = 16; \
- if (sel == 0) { \
- cargo = ctype; \
- color = 12; \
- } \
- sel--; \
- DrawString(x, y, _cargoc.names_s[ctype], color); \
- y += 10; \
- }
-
- if (_engine_refit_masks[v->engine_type]) {
- uint32 mask = _engine_refit_masks[v->engine_type];
- int cid = 0;
-
- for (; mask; mask >>= 1, cid++) {
- if (!(mask & 1)) // not this cid
- continue;
- if (!(_local_cargo_id_landscape[cid] & (1 << _opt.landscape))) // not in this landscape
- continue;
-
- show_cargo(_local_cargo_id_ctype[cid]);
- }
-
- } else { // generic refit list
- b = _aircraft_refit_types[_opt.landscape];
- do {
- show_cargo(*b);
- } while (*++b != 0xFF);
- }
-
-#undef show_cargo
-
- WP(w,refit_d).cargo = cargo;
-
- if (cargo != -1) {
- int32 cost = DoCommandByTile(v->tile, v->index, cargo, DC_QUERY_COST, CMD_REFIT_AIRCRAFT);
- if (cost != CMD_ERROR) {
+ if (WP(w,refit_d).cargo != CT_INVALID) {
+ int32 cost = DoCommandByTile(v->tile, v->index, WP(w,refit_d).cargo, DC_QUERY_COST, CMD_REFIT_AIRCRAFT);
+ if (!CmdFailed(cost)) {
SetDParam(2, cost);
- SetDParam(0, _cargoc.names_long_p[cargo]);
+ SetDParam(0, _cargoc.names_long_p[WP(w,refit_d).cargo]);
SetDParam(1, _aircraft_refit_capacity);
DrawString(1, 137, STR_A041_NEW_CAPACITY_COST_OF_REFIT, 0);
}
}
-
- break;
- }
+ } break;
case WE_CLICK:
switch(e->click.widget) {
case 2: { /* listbox */
- int y = e->click.pt.y - 25;
- if (y >= 0) {
- WP(w,refit_d).sel = y / 10;
- SetWindowDirty(w);
- }
- } break;
+ int y = e->click.pt.y - 25;
+ if (y >= 0) {
+ WP(w,refit_d).sel = y / 10;
+ SetWindowDirty(w);
+ }
+ } break;
case 4: /* refit button */
- if (WP(w,refit_d).cargo != 0xFF) {
- Vehicle *v = GetVehicle(w->window_number);
+ if (WP(w,refit_d).cargo != CT_INVALID) {
+ const Vehicle *v = GetVehicle(w->window_number);
if (DoCommandP(v->tile, v->index, WP(w,refit_d).cargo, NULL, CMD_REFIT_AIRCRAFT | CMD_MSG(STR_A042_CAN_T_REFIT_AIRCRAFT)))
DeleteWindow(w);
}
diff --git a/command.c b/command.c
index 67fbb05f0..7eae3c4fd 100644
--- a/command.c
+++ b/command.c
@@ -229,7 +229,7 @@ static CommandProc * const _command_proc_table[] = {
CmdBuildAircraft, /* 61 */
CmdSendAircraftToHangar, /* 62 */
CmdChangeAircraftServiceInt, /* 63 */
- CmdRefitAircraft, /* 64 <-- REFIT: Hackykid */
+ CmdRefitAircraft, /* 64 */
CmdPlaceSign, /* 65 */
CmdRenameSign, /* 66 */
@@ -263,7 +263,7 @@ static CommandProc * const _command_proc_table[] = {
CmdBuildShip, /* 88 */
CmdSendShipToDepot, /* 89 */
CmdChangeShipServiceInt, /* 90 */
- CmdRefitShip, /* 91 <-- REFIT: Hackykid */
+ CmdRefitShip, /* 91 */
NULL, /* 92 */
NULL, /* 93 */
@@ -284,7 +284,7 @@ static CommandProc * const _command_proc_table[] = {
CmdLevelLand, /* 105 */
- CmdRefitRailVehicle, /* 106 <-- REFIT: Hackykid */
+ CmdRefitRailVehicle, /* 106 */
CmdRestoreOrderIndex, /* 107 */
CmdBuildLock, /* 108 */
NULL, /* 109 */
diff --git a/engine.c b/engine.c
index 64d2c826a..bcbb87438 100644
--- a/engine.c
+++ b/engine.c
@@ -20,34 +20,74 @@ enum {
ENGINE_PREVIEWING = 4,
};
-/* This maps per-landscape cargo ids to globally unique cargo ids usable ie. in
- * the custom GRF files. It is basically just a transcribed table from
- * TTDPatch's newgrf.txt. */
-byte _global_cargo_id[NUM_LANDSCAPE][NUM_CARGO] = {
- /* LT_NORMAL */ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12 },
- /* LT_HILLY */ { 0, 1, 2, 3, 4, 5, 6, 7, 28, 11, 10, 12 },
- /* LT_DESERT */ { 0, 16, 2, 3, 13, 5, 6, 7, 14, 15, 10, 12 },
- /* LT_CANDY */ { 0, 17, 2, 18, 19, 20, 21, 22, 23, 24, 25, 26 },
- // 27 is paper in temperate climate in TTDPatch
- // Following can be renumbered:
- // 29 is the default cargo for the purpose of spritesets
- // 30 is the purchase list image (the equivalent of 0xff) for the purpose of spritesets
+/** TRANSLATE FROM LOCAL CARGO TO GLOBAL CARGO ID'S.
+ * This maps the per-landscape cargo ID's to globally unique cargo ID's usable ie. in
+ * the custom GRF files. It is basically just a transcribed table from TTDPatch's newgrf.txt.
+ */
+const CargoID _global_cargo_id[NUM_LANDSCAPE][NUM_CARGO] = {
+ /* LT_NORMAL */ {GC_PASSENGERS, GC_COAL, GC_MAIL, GC_OIL, GC_LIVESTOCK, GC_GOODS, GC_GRAIN, GC_WOOD, GC_IRON_ORE, GC_STEEL, GC_VALUABLES, GC_PAPER_TEMP},
+ /* LT_HILLY */ {GC_PASSENGERS, GC_COAL, GC_MAIL, GC_OIL, GC_LIVESTOCK, GC_GOODS, GC_GRAIN, GC_WOOD, GC_INVALID, GC_PAPER, GC_VALUABLES, GC_FOOD },
+ /* LT_DESERT */ {GC_PASSENGERS, GC_RUBBER,GC_MAIL, GC_OIL, GC_FRUIT, GC_GOODS, GC_GRAIN, GC_WOOD, GC_COPPER_ORE, GC_WATER, GC_VALUABLES, GC_FOOD },
+ /* LT_CANDY */ {GC_PASSENGERS, GC_SUGAR, GC_MAIL, GC_TOYS,GC_BATTERIES, GC_CANDY, GC_TOFFEE,GC_COLA, GC_COTTON_CANDY,GC_BUBBLES,GC_PLASTIC, GC_FIZZY_DRINKS },
+ /**
+ * - GC_INVALID (255) means that cargo is not available for that climate
+ * - GC_PAPER_TEMP (27) is paper in temperate climate in TTDPatch
+ * Following can be renumbered:
+ * - GC_DEFAULT (29) is the defa ult cargo for the purpose of spritesets
+ * - GC_PURCHASE (30) is the purchase list image (the equivalent of 0xff) for the purpose of spritesets
+ */
};
-/* These two arrays provide a reverse mapping. */
-byte _local_cargo_id_ctype[NUM_CID] = {
- CT_PASSENGERS, CT_COAL, CT_MAIL, CT_OIL, CT_LIVESTOCK, CT_GOODS, CT_GRAIN, CT_WOOD, // 0-7
- CT_IRON_ORE, CT_STEEL, CT_VALUABLES, CT_PAPER, CT_FOOD, CT_FRUIT, CT_COPPER_ORE, CT_WATER, // 8-15
- CT_RUBBER, CT_SUGAR, CT_TOYS, CT_BATTERIES, CT_CANDY, CT_TOFFEE, CT_COLA, CT_COTTON_CANDY, // 16-23
- CT_BUBBLES, CT_PLASTIC, CT_FIZZY_DRINKS, CT_PAPER /* unsup. */, CT_HILLY_UNUSED // 24-28
+/** BEGIN --- TRANSLATE FROM GLOBAL CARGO TO LOCAL CARGO ID'S **/
+/** Map global cargo ID's to local-cargo ID's */
+const CargoID _local_cargo_id_ctype[NUM_GLOBAL_CID] = {
+ CT_PASSENGERS,CT_COAL, CT_MAIL, CT_OIL, CT_LIVESTOCK,CT_GOODS, CT_GRAIN, CT_WOOD, /* 0- 7 */
+ CT_IRON_ORE, CT_STEEL, CT_VALUABLES, CT_PAPER, CT_FOOD, CT_FRUIT, CT_COPPER_ORE, CT_WATER, /* 8-15 */
+ CT_RUBBER, CT_SUGAR, CT_TOYS, CT_BATTERIES,CT_CANDY, CT_TOFFEE, CT_COLA, CT_COTTON_CANDY, /* 16-23 */
+ CT_BUBBLES, CT_PLASTIC,CT_FIZZY_DRINKS,CT_PAPER /* unsup. */,CT_HILLY_UNUSED, /* 24-28 */
+ CT_INVALID, CT_INVALID /* 29-30 */
};
-/* LT'th bit is set of the particular landscape if cargo available there.
- * 1: LT_NORMAL, 2: LT_HILLY, 4: LT_DESERT, 8: LT_CANDY */
-byte _local_cargo_id_landscape[NUM_CID] = {
- 15, 3, 15, 7, 3, 7, 7, 7, 1, 1, 7, 2, 7, // 0-12
- 4, 4, 4, 4, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 1, 2, // 13-28
+#define MC(cargo) (1 << cargo)
+/** Bitmasked value where the global cargo ID is available in landscape
+ * 0: LT_NORMAL, 1: LT_HILLY, 2: LT_DESERT, 3: LT_CANDY */
+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),
+ /* 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),
+ /* 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),
+ /* LT_CANDY: toyland */
+ MC(GC_PASSENGERS)|MC(GC_MAIL)|MC(GC_SUGAR)|MC(GC_TOYS)|MC(GC_BATTERIES)|MC(GC_CANDY)|
+ MC(GC_TOFFEE)|MC(GC_COLA)|MC(GC_COTTON_CANDY)|MC(GC_BUBBLES)|MC(GC_PLASTIC)|MC(GC_FIZZY_DRINKS)
+};
+/** END --- TRANSLATE FROM GLOBAL CARGO TO LOCAL CARGO ID'S **/
+
+/** Bitmasked values of what type of cargo is refittable for the given vehicle-type.
+ * This coupled with the landscape information (_landscape_global_cargo_mask) gives
+ * us exactly what is refittable and what is not */
+const uint32 _default_refitmasks[NUM_VEHICLE_TYPES] = {
+ /* Trains */
+ MC(GC_PASSENGERS)|MC(GC_COAL)|MC(GC_MAIL)|MC(GC_LIVESTOCK)|MC(GC_GOODS)|MC(GC_GRAIN)|MC(GC_WOOD)|MC(GC_IRON_ORE)|
+ MC(GC_STEEL)|MC(GC_VALUABLES)|MC(GC_PAPER)|MC(GC_FOOD)|MC(GC_FRUIT)|MC(GC_COPPER_ORE)|MC(GC_WATER)|MC(GC_SUGAR)|
+ MC(GC_TOYS)|MC(GC_CANDY)|MC(GC_TOFFEE)|MC(GC_COLA)|MC(GC_COTTON_CANDY)|MC(GC_BUBBLES)|MC(GC_PLASTIC)|MC(GC_FIZZY_DRINKS),
+ /* Road vehicles (not refittable by default) */
+ 0,
+ /* Ships */
+ MC(GC_COAL)|MC(GC_MAIL)|MC(GC_LIVESTOCK)|MC(GC_GOODS)|MC(GC_GRAIN)|MC(GC_WOOD)|MC(GC_IRON_ORE)|MC(GC_STEEL)|MC(GC_VALUABLES)|
+ MC(GC_PAPER)|MC(GC_FOOD)|MC(GC_FRUIT)|MC(GC_COPPER_ORE)|MC(GC_WATER)|MC(GC_RUBBER)|MC(GC_SUGAR)|MC(GC_TOYS)|MC(GC_BATTERIES)|
+ MC(GC_CANDY)|MC(GC_TOFFEE)|MC(GC_COLA)|MC(GC_COTTON_CANDY)|MC(GC_BUBBLES)|MC(GC_PLASTIC)|MC(GC_FIZZY_DRINKS),
+ /* Aircraft */
+ MC(GC_PASSENGERS)|MC(GC_MAIL)|MC(GC_GOODS)|MC(GC_VALUABLES)|MC(GC_FOOD)|MC(GC_FRUIT)|MC(GC_SUGAR)|MC(GC_TOYS)|
+ MC(GC_BATTERIES)|MC(GC_CANDY)|MC(GC_TOFFEE)|MC(GC_COLA)|MC(GC_COTTON_CANDY)|MC(GC_BUBBLES)|MC(GC_PLASTIC)|MC(GC_FIZZY_DRINKS),
+ /* Special/Disaster */
+ 0,0
};
+#undef MC
void ShowEnginePreviewWindow(int engine);
@@ -267,7 +307,7 @@ byte _engine_original_sprites[TOTAL_NUM_ENGINES];
// (It isn't and shouldn't be like this in the GRF files since new cargo types
// may appear in future - however it's more convenient to store it like this in
// memory. --pasky)
-static SpriteGroup _engine_custom_sprites[TOTAL_NUM_ENGINES][NUM_CID];
+static SpriteGroup _engine_custom_sprites[TOTAL_NUM_ENGINES][NUM_GLOBAL_CID];
void SetCustomEngineSprites(byte engine, byte cargo, SpriteGroup *group)
{
@@ -462,10 +502,11 @@ static RealSpriteGroup* ResolveVehicleSpriteGroup(SpriteGroup *spritegroup,
static SpriteGroup *GetVehicleSpriteGroup(byte engine, const Vehicle *v)
{
SpriteGroup *group;
- byte cargo = CID_PURCHASE;
+ byte cargo = GC_PURCHASE;
if (v != NULL) {
cargo = _global_cargo_id[_opt.landscape][v->cargo_type];
+ assert(cargo != GC_INVALID);
}
group = &_engine_custom_sprites[engine][cargo];
@@ -483,7 +524,7 @@ int GetCustomEngineSprite(byte engine, const Vehicle *v, byte direction)
{
SpriteGroup *group;
RealSpriteGroup *rsg;
- byte cargo = CID_PURCHASE;
+ byte cargo = GC_PURCHASE;
byte loaded = 0;
bool in_motion = 0;
int totalsets, spriteset;
@@ -493,6 +534,8 @@ int GetCustomEngineSprite(byte engine, const Vehicle *v, byte direction)
int capacity = v->cargo_cap;
cargo = _global_cargo_id[_opt.landscape][v->cargo_type];
+ assert(cargo != GC_INVALID);
+
if (capacity == 0) capacity = 1;
loaded = (v->cargo_count * 100) / capacity;
in_motion = (v->cur_speed != 0);
diff --git a/engine.h b/engine.h
index cbb860dc9..b588478fe 100644
--- a/engine.h
+++ b/engine.h
@@ -79,23 +79,56 @@ enum {
RVI_WAGON = 2,
};
+enum {
+ NUM_VEHICLE_TYPES = 6
+};
void AddTypeToEngines(void);
void StartupEngines(void);
-
-extern byte _global_cargo_id[NUM_LANDSCAPE][NUM_CARGO];
-enum {
- CID_DEFAULT = 29,
- CID_PURCHASE = 30,
- NUM_CID = 31,
+enum GlobalCargo {
+ GC_PASSENGERS = 0,
+ GC_COAL = 1,
+ GC_MAIL = 2,
+ GC_OIL = 3,
+ GC_LIVESTOCK = 4,
+ GC_GOODS = 5,
+ GC_GRAIN = 6, // GC_WHEAT / GC_MAIZE
+ GC_WOOD = 7,
+ GC_IRON_ORE = 8,
+ GC_STEEL = 9,
+ GC_VALUABLES = 10, // GC_GOLD / GC_DIAMONDS
+ GC_PAPER = 11,
+ GC_FOOD = 12,
+ GC_FRUIT = 13,
+ GC_COPPER_ORE = 14,
+ GC_WATER = 15,
+ GC_RUBBER = 16,
+ GC_SUGAR = 17,
+ GC_TOYS = 18,
+ GC_BATTERIES = 19,
+ GC_CANDY = 20,
+ GC_TOFFEE = 21,
+ GC_COLA = 22,
+ GC_COTTON_CANDY = 23,
+ GC_BUBBLES = 24,
+ GC_PLASTIC = 25,
+ GC_FIZZY_DRINKS = 26,
+ GC_PAPER_TEMP = 27,
+ GC_UNDEFINED = 28, // undefined; unused slot in arctic climate
+ GC_DEFAULT = 29,
+ GC_PURCHASE = 30,
+ GC_INVALID = 255,
+ NUM_GLOBAL_CID = 31
};
-extern byte _local_cargo_id_ctype[NUM_CID];
-extern byte _local_cargo_id_landscape[NUM_CID];
-extern uint32 _engine_refit_masks[256];
+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];
-extern byte _engine_original_sprites[256];
+VARDEF uint32 _engine_refit_masks[256];
+VARDEF byte _engine_original_sprites[256];
void SetWagonOverrideSprites(byte engine, struct SpriteGroup *group, byte *train_id, int trains);
void SetCustomEngineSprites(byte engine, byte cargo, struct SpriteGroup *group);
// loaded is in percents, overriding_engine 0xffff is none
diff --git a/lang/english.txt b/lang/english.txt
index c15eb9b78..892c6fae1 100644
--- a/lang/english.txt
+++ b/lang/english.txt
@@ -2445,6 +2445,7 @@ STR_882C_BUILT_VALUE :{LTBLUE}{STRING
STR_882D_VALUE :{LTBLUE}{STRING}{BLACK} Value: {LTBLUE}{CURRENCY}
STR_882E :{WHITE}{STRING}
STR_882F_LOADING_UNLOADING :{LTBLUE}Loading / Unloading
+STR_TRAIN_MUST_BE_STOPPED :{WHITE}Train must be stopped inside depot
STR_8830_CAN_T_SEND_TRAIN_TO_DEPOT :{WHITE}Can't send train to depot...
STR_8831_NO_MORE_SPACE_FOR_ORDERS :{WHITE}No more space for orders
STR_8832_TOO_MANY_ORDERS :{WHITE}Too many orders
diff --git a/newgrf.c b/newgrf.c
index 30c5a8f06..3607326aa 100644
--- a/newgrf.c
+++ b/newgrf.c
@@ -1450,8 +1450,7 @@ static void NewVehicle_SpriteGroupMapping(byte *buf, int len)
return;
}
- if (ctype == 0xFF)
- ctype = CID_PURCHASE;
+ if (ctype == GC_INVALID) ctype = GC_PURCHASE;
if (wagover) {
// TODO: No multiple cargo types per vehicle yet. --pasky
@@ -1482,7 +1481,7 @@ static void NewVehicle_SpriteGroupMapping(byte *buf, int len)
// TODO: No multiple cargo types per vehicle yet. --pasky
SetWagonOverrideSprites(engine, &_cur_grffile->spritegroups[groupid], last_engines, last_engines_count);
} else {
- SetCustomEngineSprites(engine, CID_DEFAULT, &_cur_grffile->spritegroups[groupid]);
+ SetCustomEngineSprites(engine, GC_DEFAULT, &_cur_grffile->spritegroups[groupid]);
last_engines[i] = engine;
}
}
diff --git a/ship_cmd.c b/ship_cmd.c
index 24d21fc47..b8190d6b7 100644
--- a/ship_cmd.c
+++ b/ship_cmd.c
@@ -1067,36 +1067,39 @@ int32 CmdChangeShipServiceInt(int x, int y, uint32 flags, uint32 p1, uint32 p2)
return 0;
}
-
-// p1 = vehicle
-// p2 = new cargo (0xFF)
-// p2 = skip check for stopped in hanger (0x0100)
+/** Refits a ship to the specified cargo type.
+ * @param x,y unused
+ * @param p1 vehicle ID of the ship to refit
+ * @param p2 various bitstuffed elements
+ * - p2 = (bit 0-7) - the new cargo type to refit to (p2 & 0xFF)
+ * - p2 = (bit 8) - skip check for stopped in depot, used by autoreplace (p2 & 0x100)
+ * @todo p2 bit8 check <b>NEEDS TO GO</b>
+ */
int32 CmdRefitShip(int x, int y, uint32 flags, uint32 p1, uint32 p2)
{
Vehicle *v;
int32 cost;
- byte SkipStoppedInDepotCheck = (p2 & 0x100) >> 8; //excludes the cargo value
-
- p2 = p2 & 0xFF;
+ CargoID new_cid = p2 & 0xFF; //gets the cargo number
+ bool SkipStoppedInDepotCheck = !!HASBIT(p2, 8); // XXX - needs to go, yes?
if (!IsVehicleIndex(p1)) return CMD_ERROR;
v = GetVehicle(p1);
- if (v->type != VEH_Ship || !CheckOwnership(v->owner))
- return CMD_ERROR;
-
- if (!( SkipStoppedInDepotCheck )) {
- if (!IsTileDepotType(v->tile, TRANSPORT_WATER) ||
- !(v->vehstatus&VS_STOPPED) ||
- v->u.ship.state != 0x80)
+ if (v->type != VEH_Ship || !CheckOwnership(v->owner)) return CMD_ERROR;
+ if (!SkipStoppedInDepotCheck) {
+ if (!IsTileDepotType(v->tile, TRANSPORT_WATER) || !(v->vehstatus&VS_STOPPED) || v->u.ship.state != 0x80)
return_cmd_error(STR_980B_SHIP_MUST_BE_STOPPED_IN);
- }
+ }
+
+ /* Check cargo */
+ if (!ShipVehInfo(v->engine_type)->refittable) return CMD_ERROR;
+ if (new_cid > NUM_CARGO || !CanRefitTo(v, new_cid)) return CMD_ERROR;
SET_EXPENSES_TYPE(EXPENSES_SHIP_RUN);
cost = 0;
- if (IS_HUMAN_PLAYER(v->owner) && (byte)p2 != v->cargo_type) {
+ if (IS_HUMAN_PLAYER(v->owner) && new_cid != v->cargo_type) {
cost = _price.ship_base >> 7;
}
@@ -1105,12 +1108,10 @@ int32 CmdRefitShip(int x, int y, uint32 flags, uint32 p1, uint32 p2)
//it will be checked if the cargo is valid in CmdRenewVehicle
if (!(SkipStoppedInDepotCheck))
v->cargo_count = 0;
- v->cargo_type = (byte)p2;
+ v->cargo_type = new_cid;
InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
}
return cost;
}
-
-
diff --git a/ship_gui.c b/ship_gui.c
index c0cf59e10..1e1428de2 100644
--- a/ship_gui.c
+++ b/ship_gui.c
@@ -45,23 +45,11 @@ static void DrawShipImage(const Vehicle *v, int x, int y, VehicleID selection)
}
}
-const byte _ship_refit_types[4][16] = {
- {CT_MAIL, CT_COAL, CT_LIVESTOCK, CT_GOODS, CT_GRAIN, CT_WOOD, CT_IRON_ORE, CT_STEEL, CT_VALUABLES, 255},
- {CT_MAIL, CT_COAL, CT_LIVESTOCK, CT_GOODS, CT_GRAIN, CT_WOOD, CT_PAPER, CT_FOOD, CT_VALUABLES, 255},
- {CT_MAIL, CT_FRUIT, CT_GOODS, CT_COPPER_ORE, CT_GRAIN, CT_WOOD, CT_WATER, CT_VALUABLES, 255},
- {CT_MAIL, CT_SUGAR, CT_TOYS, CT_CANDY, CT_COLA, CT_COTTON_CANDY, CT_BUBBLES, CT_TOFFEE, CT_BATTERIES, CT_PLASTIC, CT_FIZZY_DRINKS, 255},
-};
-
static void ShipRefitWndProc(Window *w, WindowEvent *e)
{
- switch(e->event) {
+ switch (e->event) {
case WE_PAINT: {
- Vehicle *v = GetVehicle(w->window_number);
- const byte *b;
- int sel;
- int x,y;
- byte color;
- int cargo;
+ const Vehicle *v = GetVehicle(w->window_number);
SetDParam(0, v->string_id);
SetDParam(1, v->unitnumber);
@@ -69,71 +57,32 @@ static void ShipRefitWndProc(Window *w, WindowEvent *e)
DrawString(1, 15, STR_983F_SELECT_CARGO_TYPE_TO_CARRY, 0);
- cargo = -1;
- x = 6;
- y = 25;
- sel = WP(w,refit_d).sel;
-
-#define show_cargo(ctype) { \
- color = 16; \
- if (sel == 0) { \
- cargo = ctype; \
- color = 12; \
- } \
- sel--; \
- DrawString(x, y, _cargoc.names_s[ctype], color); \
- y += 10; \
- }
+ /* TODO: Support for custom GRFSpecial-specified refitting! --pasky */
+ WP(w,refit_d).cargo = DrawVehicleRefitWindow(v, WP(w, refit_d).sel);;
- if (_engine_refit_masks[v->engine_type]) {
- uint32 mask = _engine_refit_masks[v->engine_type];
- int cid = 0;
-
- for (; mask; mask >>= 1, cid++) {
- if (!(mask & 1)) // not this cid
- continue;
- if (!(_local_cargo_id_landscape[cid] & (1 << _opt.landscape))) // not in this landscape
- continue;
-
- show_cargo(_local_cargo_id_ctype[cid]);
- }
-
- } else { // generic refit list
- b = _ship_refit_types[_opt.landscape];
- do {
- show_cargo(*b);
- } while (*++b != 255);
- }
-
-#undef show_cargo
-
- WP(w,refit_d).cargo = cargo;
-
- if (cargo != -1) {
- int32 cost = DoCommandByTile(v->tile, v->index, cargo, 0, CMD_REFIT_SHIP);
- if (cost != CMD_ERROR) {
+ if (WP(w,refit_d).cargo != CT_INVALID) {
+ int32 cost = DoCommandByTile(v->tile, v->index, WP(w,refit_d).cargo, DC_QUERY_COST, CMD_REFIT_SHIP);
+ if (!CmdFailed(cost)) {
SetDParam(2, cost);
- SetDParam(0, _cargoc.names_long_p[cargo]);
+ SetDParam(0, _cargoc.names_long_p[WP(w,refit_d).cargo]);
SetDParam(1, v->cargo_cap);
DrawString(1, 137, STR_9840_NEW_CAPACITY_COST_OF_REFIT, 0);
}
}
-
- break;
- }
+ } break;
case WE_CLICK:
switch(e->click.widget) {
case 2: { /* listbox */
- int y = e->click.pt.y - 25;
- if (y >= 0) {
- WP(w,refit_d).sel = y / 10;
- SetWindowDirty(w);
- }
- } break;
+ int y = e->click.pt.y - 25;
+ if (y >= 0) {
+ WP(w,refit_d).sel = y / 10;
+ SetWindowDirty(w);
+ }
+ } break;
case 4: /* refit button */
- if (WP(w,refit_d).cargo != 0xFF) {
- Vehicle *v = GetVehicle(w->window_number);
+ if (WP(w,refit_d).cargo != CT_INVALID) {
+ const Vehicle *v = GetVehicle(w->window_number);
if (DoCommandP(v->tile, v->index, WP(w,refit_d).cargo, NULL, CMD_REFIT_SHIP | CMD_MSG(STR_9841_CAN_T_REFIT_SHIP)))
DeleteWindow(w);
}
diff --git a/station.h b/station.h
index 08c3e01c0..608688fc7 100644
--- a/station.h
+++ b/station.h
@@ -248,7 +248,7 @@ typedef struct StationSpec {
StationLayout **layouts;
/* Sprite offsets for renderdata->seq->image. spritegroup[0] is default
- * whilst spritegroup[1] is "CID_PURCHASE". */
+ * whilst spritegroup[1] is "GC_PURCHASE". */
SpriteGroup spritegroup[2];
} StationSpec;
diff --git a/train_cmd.c b/train_cmd.c
index 255ede174..95770e442 100644
--- a/train_cmd.c
+++ b/train_cmd.c
@@ -1282,25 +1282,31 @@ int32 CmdForceTrainProceed(int x, int y, uint32 flags, uint32 p1, uint32 p2)
return 0;
}
-// p1 = vehicle to refit
-// p2 = new cargo (0xFF)
-// p2 = skip check for stopped in hanger (0x0100)
+/** Refits a train to the specified cargo type.
+ * @param x,y unused
+ * @param p1 vehicle ID of the train to refit
+ * @param p2 various bitstuffed elements
+ * - p2 = (bit 0-7) - the new cargo type to refit to (p2 & 0xFF)
+ * - p2 = (bit 8) - skip check for stopped in depot, used by autoreplace (p2 & 0x100)
+ * @todo p2 bit8 check <b>NEEDS TO GO</b>
+ */
int32 CmdRefitRailVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2)
{
Vehicle *v;
int32 cost;
uint num;
-
- byte SkipStoppedInDepotCheck = (p2 & 0x100) >> 8;
-
- p2 = p2 & 0xFF;
+ CargoID new_cid = p2 & 0xFF; //gets the cargo number
+ bool SkipStoppedInDepotCheck = !!HASBIT(p2, 8); // XXX - needs to go, yes?
if (!IsVehicleIndex(p1)) return CMD_ERROR;
v = GetVehicle(p1);
- if (v->type != VEH_Train || !CheckOwnership(v->owner) || ((CheckTrainStoppedInDepot(v) < 0) && !(SkipStoppedInDepotCheck)))
- return CMD_ERROR;
+ if (v->type != VEH_Train || !CheckOwnership(v->owner)) return CMD_ERROR;
+ if (!SkipStoppedInDepotCheck && CheckTrainStoppedInDepot(v) < 0) return_cmd_error(STR_TRAIN_MUST_BE_STOPPED);
+
+ /* Check cargo */
+ if (new_cid > NUM_CARGO) return CMD_ERROR;
SET_EXPENSES_TYPE(EXPENSES_TRAIN_RUN);
@@ -1311,17 +1317,17 @@ int32 CmdRefitRailVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2)
/* XXX: We also refit all the attached wagons en-masse if they
* can be refitted. This is how TTDPatch does it. TODO: Have
* some nice [Refit] button near each wagon. --pasky */
- if ((!(RailVehInfo(v->engine_type)->flags & RVI_WAGON)
- || (_engine_refit_masks[v->engine_type] & (1 << p2)))
- && (byte) p2 != v->cargo_type && v->cargo_cap != 0) {
+ if (!CanRefitTo(v, new_cid)) continue;
+
+ if (new_cid != v->cargo_type && v->cargo_cap != 0) {
cost += (_price.build_railvehicle >> 8);
num += v->cargo_cap;
if (flags & DC_EXEC) {
- //autorefitted train cars wants to keep the cargo
- //it will be checked if the cargo is valid in CmdReplaceVehicle
+ //autorefitted train cars wants to keep the cargo
+ //it will be checked if the cargo is valid in CmdReplaceVehicle
if (!(SkipStoppedInDepotCheck))
v->cargo_count = 0;
- v->cargo_type = (byte)p2;
+ v->cargo_type = new_cid;
InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
}
}
diff --git a/train_gui.c b/train_gui.c
index c6bcf66cd..3cc68811f 100644
--- a/train_gui.c
+++ b/train_gui.c
@@ -662,23 +662,11 @@ void ShowTrainDepotWindow(uint tile)
}
}
-const byte _rail_vehicle_refit_types[4][16] = {
- { 0,1,2,4,5,6,7,8,9,10,0xFF }, // normal
- { 0,1,4,5,6,7,9,11,10,0xFF }, // arctic
- { 0,4,5,8,6,7,9,10,0xFF }, // desert
- { 0,1,3,5,7,8,9,6,4,10,11,0xFF }// candy
-};
-
static void RailVehicleRefitWndProc(Window *w, WindowEvent *e)
{
- switch(e->event) {
+ switch (e->event) {
case WE_PAINT: {
- Vehicle *v = GetVehicle(w->window_number);
- const byte *b;
- int sel;
- int x,y;
- byte color;
- int cargo;
+ const Vehicle *v = GetVehicle(w->window_number);
SetDParam(0, v->string_id);
SetDParam(1, v->unitnumber);
@@ -686,57 +674,19 @@ static void RailVehicleRefitWndProc(Window *w, WindowEvent *e)
DrawString(1, 15, STR_983F_SELECT_CARGO_TYPE_TO_CARRY, 0);
- cargo = -1;
- x = 6;
- y = 25;
- sel = WP(w,refit_d).sel;
-
-#define show_cargo(ctype) { \
- color = 16; \
- if (sel == 0) { \
- cargo = ctype; \
- color = 12; \
- } \
- sel--; \
- DrawString(x, y, _cargoc.names_s[ctype], color); \
- y += 10; \
- }
-
- if (_engine_refit_masks[v->engine_type]) {
- uint32 mask = _engine_refit_masks[v->engine_type];
- int cid = 0;
-
- for (; mask; mask >>= 1, cid++) {
- if (!(mask & 1)) // not this cid
- continue;
- if (!(_local_cargo_id_landscape[cid] & (1 << _opt.landscape))) // not in this landscape
- continue;
-
- show_cargo(_local_cargo_id_ctype[cid]);
- }
+ /* TODO: Support for custom GRFSpecial-specified refitting! --pasky */
+ WP(w,refit_d).cargo = DrawVehicleRefitWindow(v, WP(w, refit_d).sel);
- } else { // generic refit list
- b = _rail_vehicle_refit_types[_opt.landscape];
- do {
- show_cargo(*b);
- } while (*++b != 255);
- }
-
-#undef show_cargo
-
- WP(w,refit_d).cargo = cargo;
-
- if (cargo != -1) {
- int32 cost = DoCommandByTile(v->tile, v->index, cargo, 0, CMD_REFIT_RAIL_VEHICLE);
- if (cost != CMD_ERROR) {
+ if (WP(w,refit_d).cargo != CT_INVALID) {
+ int32 cost = DoCommandByTile(v->tile, v->index, WP(w,refit_d).cargo, DC_QUERY_COST, CMD_REFIT_RAIL_VEHICLE);
+ if (!CmdFailed(cost)) {
SetDParam(2, cost);
- SetDParam(0, _cargoc.names_long_p[cargo]);
+ SetDParam(0, _cargoc.names_long_p[WP(w,refit_d).cargo]);
SetDParam(1, _returned_refit_amount);
DrawString(1, 137, STR_9840_NEW_CAPACITY_COST_OF_REFIT, 0);
}
}
- break;
- }
+ } break;
case WE_CLICK:
switch(e->click.widget) {
@@ -748,8 +698,8 @@ static void RailVehicleRefitWndProc(Window *w, WindowEvent *e)
}
} break;
case 4: /* refit button */
- if (WP(w,refit_d).cargo != 0xFF) {
- Vehicle *v = GetVehicle(w->window_number);
+ if (WP(w,refit_d).cargo != CT_INVALID) {
+ const Vehicle *v = GetVehicle(w->window_number);
if (DoCommandP(v->tile, v->index, WP(w,refit_d).cargo, NULL, CMD_REFIT_RAIL_VEHICLE | CMD_MSG(STR_RAIL_CAN_T_REFIT_VEHICLE)))
DeleteWindow(w);
}
@@ -809,9 +759,9 @@ static Widget _train_view_widgets[] = {
static void TrainViewWndProc(Window *w, WindowEvent *e)
{
- switch(e->event) {
+ switch (e->event) {
case WE_PAINT: {
- Vehicle *v, *u;
+ const Vehicle *v, *u;
StringID str;
v = GetVehicle(w->window_number);
@@ -820,22 +770,16 @@ static void TrainViewWndProc(Window *w, WindowEvent *e)
SETBIT(w->disabled_state, 12);
- /* See if any carriage can be refitted */
+ /* 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_refit_masks[u->engine_type] != 0 ||
+ (!(RailVehInfo(v->engine_type)->flags & RVI_WAGON) && v->cargo_cap != 0)) {
CLRBIT(w->disabled_state, 12);
/* We have a refittable carriage, bail out */
break;
}
}
- /* Above code doesn't seem to handle non-newgrf engines, do it separately
- TODO: handle engines which are NOT the head of the train, but don't break wagons */
- if (v->cargo_cap != 0) {
- /* we can refit this engine */
- CLRBIT(w->disabled_state, 12);
- }
-
/* draw widgets & caption */
SetDParam(0, v->string_id);
SetDParam(1, v->unitnumber);
diff --git a/ttd.h b/ttd.h
index 3c9e4ae2b..018198779 100644
--- a/ttd.h
+++ b/ttd.h
@@ -67,6 +67,7 @@ typedef struct DrawPixelInfo DrawPixelInfo;
typedef uint16 VehicleID;
typedef byte PlayerID;
typedef byte OrderID;
+typedef byte CargoID;
typedef uint16 StringID;
typedef uint16 SpriteID;
typedef uint32 PalSpriteID;
diff --git a/vehicle.c b/vehicle.c
index 025bb0679..a705ed93b 100644
--- a/vehicle.c
+++ b/vehicle.c
@@ -501,6 +501,28 @@ bool CanFillVehicle(Vehicle *v)
return false;
}
+/** Check if a given vehicle (type) can be refitted to a given cargo
+ * @param *v vehicle to check
+ * @param cid_to check refit to this cargo-type
+ * @return true if it is possible, false otherwise
+ */
+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;
+}
+
static void DoDrawVehicle(Vehicle *v)
{
uint32 image = v->cur_image;
diff --git a/vehicle.h b/vehicle.h
index a86a1ce37..f0699b5a6 100644
--- a/vehicle.h
+++ b/vehicle.h
@@ -262,6 +262,7 @@ Vehicle *FindVehicleOnTileZ(TileIndex tile, byte z);
void InitializeTrains(void);
bool CanFillVehicle(Vehicle *v);
+bool CanRefitTo(const Vehicle *v, CargoID cid_to);
void ViewportAddVehicles(DrawPixelInfo *dpi);
diff --git a/vehicle_gui.c b/vehicle_gui.c
index 5832498e8..c83f287ec 100644
--- a/vehicle_gui.c
+++ b/vehicle_gui.c
@@ -165,6 +165,42 @@ void DrawVehicleProfitButton(Vehicle *v, int x, int y)
DrawSprite(SPR_BLOT | ormod, x, y);
}
+/** Draw the list of available refit options.
+ * Draw the list and highlight the selected refit option (if any)
+ * @param *v vehicle(type) to get the refit-options of
+ * @param sel selected refit cargo-type in the window
+ * @return the cargo type that is hightlighted, CT_INVALID if none
+ */
+CargoID DrawVehicleRefitWindow(const Vehicle *v, int sel)
+{
+ uint32 cmask;
+ CargoID cid, cargo = CT_INVALID;
+ int y = 25;
+#define show_cargo(ctype) { \
+ byte colour = 16; \
+ if (sel == 0) { \
+ cargo = ctype; \
+ colour = 12; \
+} \
+ sel--; \
+ DrawString(6, y, _cargoc.names_s[ctype], colour); \
+ y += 10; \
+}
+
+ /* Check if engine has custom refit or normal ones, and get its bitmasked value.
+ * Now just and it with the bitmasked available cargo on the current landscape, and
+ * where the bits are set: those are available */
+ cmask = (_engine_refit_masks[v->engine_type] != 0) ? _engine_refit_masks[v->engine_type] : _default_refitmasks[v->type - VEH_Train];
+ 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
+ show_cargo(_local_cargo_id_ctype[cid]);
+ }
+ return cargo;
+}
+
/************ Sorter functions *****************/
int CDECL GeneralOwnerSorter(const void *a, const void *b)
{
diff --git a/vehicle_gui.h b/vehicle_gui.h
index 1af4e0aba..a4e010c69 100644
--- a/vehicle_gui.h
+++ b/vehicle_gui.h
@@ -6,6 +6,7 @@
struct vehiclelist_d;
void DrawVehicleProfitButton(Vehicle *v, int x, int y);
+CargoID DrawVehicleRefitWindow(const Vehicle *v, int sel);
void InitializeVehiclesGuiList(void);
/* sorter stuff */