Changeset - r4574:26f71b3f860b
[Not reviewed]
master
0 10 0
bjarni - 18 years ago 2006-09-08 10:47:39
bjarni@openttd.org
(svn r6424) -Codechange: [autoreplace] removed a loop though all vehicles from each time the window is redrawn
To do this, the player struct contains an array, that contains the count of each engine type that the player owns
Those arrays are updated each time a vehicle is build or deleted and is calculated on load (it's not saved)
It's possible to access the arrays outside of the autoreplace GUI, so feel free to read from them in other patches as well
10 files changed with 60 insertions and 40 deletions:
0 comments (0 inline, 0 general)
aircraft_cmd.c
Show inline comments
 
@@ -387,24 +387,25 @@ int32 CmdBuildAircraft(TileIndex tile, u
 
			w->x_offs = w->y_offs = -1;
 
			w->sprite_width = w->sprite_height = 2;
 
			w->z_height = 1;
 
			w->vehstatus = VS_HIDDEN | VS_UNCLICKABLE;
 
			w->spritenum = 0xFF;
 
			w->subtype = 6;
 
			w->cur_image = SPR_ROTOR_STOPPED;
 
			w->random_bits = VehicleRandomBits();
 
			/* Use rotor's air.state to store the rotor animation frame */
 
			w->u.air.state = HRS_ROTOR_STOPPED;
 
			VehiclePositionChanged(w);
 
		}
 
		GetPlayer(_current_player)->num_engines[p1]++;
 

	
 
		InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
 
		RebuildVehicleLists();
 
		InvalidateWindow(WC_COMPANY, v->owner);
 
		if (IsLocalPlayer())
 
			InvalidateWindow(WC_REPLACE_VEHICLE, VEH_Aircraft); //updates the replace Aircraft window
 
	}
 

	
 
	return value;
 
}
 

	
 

	
openttd.c
Show inline comments
 
@@ -1447,24 +1447,38 @@ bool AfterLoadGame(void)
 
		Station *st;
 
		FOR_ALL_STATIONS(st) {
 
			st->last_vehicle_type = VEH_Invalid;
 
		}
 
	}
 

	
 
	YapfNotifyTrackLayoutChange(INVALID_TILE, INVALID_TRACK);
 

	
 
	FOR_ALL_PLAYERS(p) p->avail_railtypes = GetPlayerRailtypes(p->index);
 

	
 
	if (!CheckSavegameVersion(27)) AfterLoadStations();
 

	
 
	{
 
		/* Set up the engine count for all players */
 
		Player *players[MAX_PLAYERS];
 
		int i;
 
		const Vehicle *v;
 

	
 
		for (i = 0; i < MAX_PLAYERS; i++) players[i] = GetPlayer(i);
 

	
 
		FOR_ALL_VEHICLES(v) {
 
			if (!IsEngineCountable(v)) continue;
 
			players[v->owner]->num_engines[v->engine_type]++;
 
		}
 
	}
 

	
 
	/* Time starts at 0 instead of 1920.
 
	 * Account for this in older games by adding an offset */
 
	if (CheckSavegameVersion(31)) {
 
		Station *st;
 
		Waypoint *wp;
 
		Engine *e;
 
		Player *player;
 
		Industry *i;
 
		Vehicle *v;
 

	
 
		_date += DAYS_TILL_ORIGINAL_BASE_YEAR;
 
		_cur_year += ORIGINAL_BASE_YEAR;
player.h
Show inline comments
 
@@ -185,24 +185,25 @@ typedef struct Player {
 
	bool is_ai;
 
	PlayerAI ai;
 
	PlayerAiNew ainew;
 

	
 
	int64 yearly_expenses[3][13];
 
	PlayerEconomyEntry cur_economy;
 
	PlayerEconomyEntry old_economy[24];
 
	EngineRenewList engine_renew_list; // Defined later
 
	bool engine_renew;
 
	bool renew_keep_length;
 
	int16 engine_renew_months;
 
	uint32 engine_renew_money;
 
	uint16 num_engines[TOTAL_NUM_ENGINES]; // caches the number of engines of each type the player owns (no need to save this)
 
} Player;
 

	
 
uint16 GetDrawStringPlayerColor(PlayerID player);
 

	
 
void ChangeOwnershipOfPlayerItems(PlayerID old_player, PlayerID new_player);
 
void GetNameOfOwner(PlayerID owner, TileIndex tile);
 
int64 CalculateCompanyValue(const Player* p);
 
void InvalidatePlayerWindows(const Player* p);
 
void UpdatePlayerMoney32(Player *p);
 
#define FOR_ALL_PLAYERS(p) for (p = _players; p != endof(_players); p++)
 

	
 
VARDEF PlayerID _local_player;
players.c
Show inline comments
 
@@ -511,24 +511,26 @@ Player *DoStartupNewPlayer(bool is_ai)
 
	p->engine_renew_months = -6;
 
	p->engine_renew_money = 100000;
 

	
 
	GeneratePresidentName(p);
 

	
 
	InvalidateWindow(WC_GRAPH_LEGEND, 0);
 
	InvalidateWindow(WC_TOOLBAR_MENU, 0);
 
	InvalidateWindow(WC_CLIENT_LIST, 0);
 

	
 
	if (is_ai && (!_networking || _network_server) && _ai.enabled)
 
		AI_StartNewAI(p->index);
 

	
 
	memset(p->num_engines, 0, TOTAL_NUM_ENGINES);
 

	
 
	return p;
 
}
 

	
 
void StartupPlayers(void)
 
{
 
	// The AI starts like in the setting with +2 month max
 
	_next_competitor_start = _opt.diff.competitor_start_time * 90 * DAY_TICKS + RandomRange(60 * DAY_TICKS) + 1;
 
}
 

	
 
static void MaybeStartNewPlayer(void)
 
{
 
	uint n;
roadveh_cmd.c
Show inline comments
 
@@ -182,24 +182,25 @@ int32 CmdBuildRoadVeh(TileIndex tile, ui
 
		v->string_id = STR_SV_ROADVEH_NAME;
 

	
 
		v->service_interval = _patches.servint_roadveh;
 

	
 
		v->date_of_last_service = _date;
 
		v->build_year = _cur_year;
 

	
 
		v->type = VEH_Road;
 
		v->cur_image = 0xC15;
 
		v->random_bits = VehicleRandomBits();
 

	
 
		VehiclePositionChanged(v);
 
		GetPlayer(_current_player)->num_engines[p1]++;
 

	
 
		InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
 
		RebuildVehicleLists();
 
		InvalidateWindow(WC_COMPANY, v->owner);
 
		if (IsLocalPlayer())
 
			InvalidateWindow(WC_REPLACE_VEHICLE, VEH_Road); // updates the replace Road window
 
	}
 

	
 
	return cost;
 
}
 

	
 
/** Start/Stop a road vehicle.
ship_cmd.c
Show inline comments
 
@@ -905,24 +905,25 @@ int32 CmdBuildShip(TileIndex tile, uint3
 

	
 
		v->string_id = STR_SV_SHIP_NAME;
 
		v->u.ship.state = 0x80;
 

	
 
		v->service_interval = _patches.servint_ships;
 
		v->date_of_last_service = _date;
 
		v->build_year = _cur_year;
 
		v->cur_image = 0x0E5E;
 
		v->type = VEH_Ship;
 
		v->random_bits = VehicleRandomBits();
 

	
 
		VehiclePositionChanged(v);
 
		GetPlayer(_current_player)->num_engines[p1]++;
 

	
 
		InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
 
		RebuildVehicleLists();
 
		InvalidateWindow(WC_COMPANY, v->owner);
 
		if (IsLocalPlayer())
 
			InvalidateWindow(WC_REPLACE_VEHICLE, VEH_Ship); // updates the replace Ship window
 
	}
 

	
 
	return value;
 
}
 

	
 
/** Sell a ship.
train_cmd.c
Show inline comments
 
@@ -626,24 +626,25 @@ static int32 CmdBuildRailWagon(EngineID 
 

	
 
			v->build_year = _cur_year;
 
			v->type = VEH_Train;
 
			v->cur_image = 0xAC2;
 
			v->random_bits = VehicleRandomBits();
 

	
 
			AddArticulatedParts(vl);
 

	
 
			_new_vehicle_id = v->index;
 

	
 
			VehiclePositionChanged(v);
 
			TrainConsistChanged(GetFirstVehicleInChain(v));
 
			GetPlayer(_current_player)->num_engines[engine]++;
 

	
 
			InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
 
			if (IsLocalPlayer()) {
 
				InvalidateWindow(WC_REPLACE_VEHICLE, VEH_Train); // updates the replace Train window
 
			}
 
		}
 
	}
 

	
 
	return value;
 
}
 

	
 
// Move all free vehicles in the depot to the train
 
@@ -806,24 +807,25 @@ int32 CmdBuildRailVehicle(TileIndex tile
 
				vl[1]->u.rail.other_multiheaded_part = vl[0];
 
			} else {
 
				AddArticulatedParts(vl);
 
			}
 

	
 
			TrainConsistChanged(v);
 
			UpdateTrainAcceleration(v);
 

	
 
			if (!HASBIT(p2, 1)) { // check if the cars should be added to the new vehicle
 
				NormalizeTrainVehInDepot(v);
 
			}
 

	
 
			GetPlayer(_current_player)->num_engines[p1]++;
 
			InvalidateWindow(WC_VEHICLE_DEPOT, tile);
 
			RebuildVehicleLists();
 
			InvalidateWindow(WC_COMPANY, v->owner);
 
			if (IsLocalPlayer()) {
 
				InvalidateWindow(WC_REPLACE_VEHICLE, VEH_Train); // updates the replace Train window
 
			}
 
		}
 
	}
 

	
 
	return value;
 
}
 

	
vehicle.c
Show inline comments
 
@@ -526,26 +526,46 @@ Vehicle *GetFirstVehicleInChain(const Ve
 
		for (u = (Vehicle *)v; u != NULL; u = u->next) u->first = (Vehicle *)v;
 

	
 
	return (Vehicle*)v;
 
}
 

	
 
uint CountVehiclesInChain(const Vehicle* v)
 
{
 
	uint count = 0;
 
	do count++; while ((v = v->next) != NULL);
 
	return count;
 
}
 

	
 
/** Check if a vehicle is counted in num_engines in each player struct
 
 * @param *v Vehicle to test
 
 * @return true if the vehicle is counted in num_engines
 
 */
 
bool IsEngineCountable(const Vehicle *v)
 
{
 
	switch (v->type) {
 
		case VEH_Aircraft: return (v->subtype <= 2); // don't count plane shadows and helicopter rotors
 
		case VEH_Train:
 
			return !IsArticulatedPart(v) && // tenders and other articulated parts
 
			(!IsMultiheaded(v) || IsTrainEngine(v)); // rear parts of multiheaded engines
 
		case VEH_Road:
 
		case VEH_Ship:
 
			return true;
 
		default: return false; // Only count player buildable vehicles
 
	}
 
}
 

	
 
void DestroyVehicle(Vehicle *v)
 
{
 
	if (IsEngineCountable(v)) GetPlayer(v->owner)->num_engines[v->engine_type]--;
 

	
 
	DeleteVehicleNews(v->index, INVALID_STRING_ID);
 

	
 
	DeleteName(v->string_id);
 
	if (v->type == VEH_Road) ClearSlot(v);
 

	
 
	UpdateVehiclePosHash(v, INVALID_COORD, 0);
 
	v->next_hash = INVALID_VEHICLE;
 
	if (v->orders != NULL) DeleteVehicleOrders(v);
 

	
 
	/* Now remove any artic part. This will trigger an other
 
	 *  destroy vehicle, which on his turn can remove any
 
	 *  other artic parts. */
vehicle.h
Show inline comments
 
@@ -246,24 +246,25 @@ typedef void *VehicleFromPosProc(Vehicle
 

	
 
void VehicleServiceInDepot(Vehicle *v);
 
Vehicle *AllocateVehicle(void);
 
bool AllocateVehicles(Vehicle **vl, int num);
 
Vehicle *ForceAllocateVehicle(void);
 
Vehicle *ForceAllocateSpecialVehicle(void);
 
void VehiclePositionChanged(Vehicle *v);
 
void AfterLoadVehicles(void);
 
Vehicle *GetLastVehicleInChain(Vehicle *v);
 
Vehicle *GetPrevVehicleInChain(const Vehicle *v);
 
Vehicle *GetFirstVehicleInChain(const Vehicle *v);
 
uint CountVehiclesInChain(const Vehicle* v);
 
bool IsEngineCountable(const Vehicle *v);
 
void DeleteVehicleChain(Vehicle *v);
 
void *VehicleFromPos(TileIndex tile, void *data, VehicleFromPosProc *proc);
 
void CallVehicleTicks(void);
 
Vehicle *FindVehicleOnTileZ(TileIndex tile, byte z);
 

	
 
void InitializeTrains(void);
 
byte VehicleRandomBits(void);
 

	
 
bool CanFillVehicle(Vehicle *v);
 
bool CanRefitTo(EngineID engine_type, CargoID cid_to);
 
CargoID FindFirstRefittableCargo(EngineID engine_type);
 
int32 GetRefitCost(EngineID engine_type);
vehicle_gui.c
Show inline comments
 
@@ -40,25 +40,24 @@ static Sorting _sorting;
 
typedef struct vehiclelist_d {
 
	const Vehicle** sort_list; // list of vehicles (sorted)
 
	Listing *_sorting;         // pointer to the appropiate subcategory of _sorting
 
	byte vehicle_type;         // the vehicle type that is sorted
 
	list_d l;                  // general list struct
 
} vehiclelist_d;
 
assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(vehiclelist_d));
 

	
 
static uint32 _internal_name_sorter_id; // internal StringID for default vehicle-names
 
static const Vehicle* _last_vehicle; // cached vehicle to hopefully speed up name-sorting
 
static bool   _internal_sort_order;     // descending/ascending
 

	
 
static uint16 _player_num_engines[TOTAL_NUM_ENGINES];
 
static RailType _railtype_selected_in_replace_gui;
 

	
 

	
 
typedef int CDECL VehicleSortListingTypeFunction(const void*, const void*);
 

	
 
static VehicleSortListingTypeFunction VehicleNumberSorter;
 
static VehicleSortListingTypeFunction VehicleNameSorter;
 
static VehicleSortListingTypeFunction VehicleAgeSorter;
 
static VehicleSortListingTypeFunction VehicleProfitThisYearSorter;
 
static VehicleSortListingTypeFunction VehicleProfitLastYearSorter;
 
static VehicleSortListingTypeFunction VehicleCargoSorter;
 
static VehicleSortListingTypeFunction VehicleReliabilitySorter;
 
@@ -434,25 +433,25 @@ static void train_engine_drawing_loop(in
 
	uint8 lines_drawn, bool is_engine, bool show_cars, bool show_outdated, bool show_compatible)
 
{
 
	EngineID j;
 
	byte colour;
 
	const Player *p = GetPlayer(_local_player);
 

	
 
	for (j = 0; j < NUM_TRAIN_ENGINES; j++) {
 
		EngineID i = GetRailVehAtPosition(j);
 
		const Engine *e = GetEngine(i);
 
		const RailVehicleInfo *rvi = RailVehInfo(i);
 
		const EngineInfo *info = EngInfo(i);
 

	
 
		if (!EngineHasReplacementForPlayer(p, i) && _player_num_engines[i] == 0 && show_outdated) continue;
 
		if (!EngineHasReplacementForPlayer(p, i) && p->num_engines[i] == 0 && show_outdated) continue;
 

	
 
		if ((rvi->power == 0 && !show_cars) || (rvi->power != 0 && show_cars))  // show wagons or engines (works since wagons do not have power)
 
			continue;
 

	
 
		if (*sel == 0) *selected_id = j;
 

	
 

	
 
		colour = *sel == 0 ? 0xC : 0x10;
 
		if (!(ENGINE_AVAILABLE && show_outdated && RailVehInfo(i)->power && IsCompatibleRail(e->railtype, railtype))) {
 
			if ((!IsCompatibleRail(e->railtype, railtype) && show_compatible)
 
				|| (e->railtype != railtype && !show_compatible)
 
				|| !(rvi->flags & RVI_WAGON) != is_engine ||
 
@@ -461,28 +460,28 @@ static void train_engine_drawing_loop(in
 
#if 0
 
		} else {
 
			// TODO find a nice red colour for vehicles being replaced
 
			if ( _autoreplace_array[i] != i )
 
				colour = *sel == 0 ? 0x44 : 0x45;
 
#endif
 
		}
 

	
 
		if (IS_INT_INSIDE(--*pos, -lines_drawn, 0)) {
 
			DrawString(*x + 59, *y + 2, GetCustomEngineName(i),
 
				colour);
 
			// show_outdated is true only for left side, which is where we show old replacements
 
			DrawTrainEngine(*x + 29, *y + 6, i, (_player_num_engines[i] == 0 && show_outdated) ?
 
			DrawTrainEngine(*x + 29, *y + 6, i, (p->num_engines[i] == 0 && show_outdated) ?
 
				PALETTE_CRASH : GetEnginePalette(i, _local_player));
 
			if ( show_outdated ) {
 
				SetDParam(0, _player_num_engines[i]);
 
				SetDParam(0, p->num_engines[i]);
 
				DrawStringRightAligned(213, *y+5, STR_TINY_BLACK, 0);
 
			}
 
			*y += 14;
 
		}
 
		--*sel;
 
	}
 
}
 

	
 

	
 
static void SetupScrollStuffForReplaceWindow(Window *w)
 
{
 
	EngineID selected_id[2] = { INVALID_ENGINE, INVALID_ENGINE };
 
@@ -501,62 +500,62 @@ static void SetupScrollStuffForReplaceWi
 

	
 
			w->widget[13].color = _player_colors[_local_player]; // sets the colour of that art thing
 
			w->widget[16].color = _player_colors[_local_player]; // sets the colour of that art thing
 

	
 
			for (i = 0; i < NUM_TRAIN_ENGINES; i++) {
 
				EngineID eid = GetRailVehAtPosition(i);
 
				const Engine* e = GetEngine(eid);
 
				const EngineInfo* info = EngInfo(eid);
 

	
 
				// left window contains compatible engines while right window only contains engines of the selected type
 
				if (ENGINE_AVAILABLE &&
 
						(RailVehInfo(eid)->power != 0) == (WP(w, replaceveh_d).wagon_btnstate != 0)) {
 
					if (IsCompatibleRail(e->railtype, railtype) && (_player_num_engines[eid] > 0 || EngineHasReplacementForPlayer(p, eid))) {
 
					if (IsCompatibleRail(e->railtype, railtype) && (p->num_engines[eid] > 0 || EngineHasReplacementForPlayer(p, eid))) {
 
						if (sel[0] == count) selected_id[0] = eid;
 
						count++;
 
					}
 
					if (e->railtype == railtype && HASBIT(e->player_avail, _local_player)) {
 
						if (sel[1] == count2) selected_id[1] = eid;
 
						count2++;
 
					}
 
				}
 
			}
 
			break;
 
		}
 

	
 
		case VEH_Road: {
 
			for (i = ROAD_ENGINES_INDEX; i < ROAD_ENGINES_INDEX + NUM_ROAD_ENGINES; i++) {
 
				if (_player_num_engines[i] > 0 || EngineHasReplacementForPlayer(p, i)) {
 
				if (p->num_engines[i] > 0 || EngineHasReplacementForPlayer(p, i)) {
 
					if (sel[0] == count) selected_id[0] = i;
 
					count++;
 
				}
 
			}
 

	
 
			if (selected_id[0] != INVALID_ENGINE) { // only draw right array if we have anything in the left one
 
				CargoID cargo = RoadVehInfo(selected_id[0])->cargo_type;
 

	
 
				for (i = ROAD_ENGINES_INDEX; i < ROAD_ENGINES_INDEX + NUM_ROAD_ENGINES; i++) {
 
					if (cargo == RoadVehInfo(i)->cargo_type &&
 
							HASBIT(GetEngine(i)->player_avail, _local_player)) {
 
						if (sel[1] == count2) selected_id[1] = i;
 
						count2++;
 
					}
 
				}
 
			}
 
			break;
 
		}
 

	
 
		case VEH_Ship: {
 
			for (i = SHIP_ENGINES_INDEX; i < SHIP_ENGINES_INDEX + NUM_SHIP_ENGINES; i++) {
 
				if (_player_num_engines[i] > 0 || EngineHasReplacementForPlayer(p, i)) {
 
				if (p->num_engines[i] > 0 || EngineHasReplacementForPlayer(p, i)) {
 
					if (sel[0] == count) selected_id[0] = i;
 
					count++;
 
				}
 
			}
 

	
 
			if (selected_id[0] != INVALID_ENGINE) {
 
				const ShipVehicleInfo* svi = ShipVehInfo(selected_id[0]);
 
				CargoID cargo = svi->cargo_type;
 
				byte refittable = svi->refittable;
 

	
 
				for (i = SHIP_ENGINES_INDEX; i < SHIP_ENGINES_INDEX + NUM_SHIP_ENGINES; i++) {
 
					if (HASBIT(GetEngine(i)->player_avail, _local_player) && (
 
@@ -564,25 +563,25 @@ static void SetupScrollStuffForReplaceWi
 
								ShipVehInfo(i)->refittable & refittable
 
							)) {
 
						if (sel[1] == count2) selected_id[1] = i;
 
						count2++;
 
					}
 
				}
 
			}
 
			break;
 
		}
 

	
 
		case VEH_Aircraft: {
 
			for (i = AIRCRAFT_ENGINES_INDEX; i < AIRCRAFT_ENGINES_INDEX + NUM_AIRCRAFT_ENGINES; i++) {
 
				if (_player_num_engines[i] > 0 || EngineHasReplacementForPlayer(p, i)) {
 
				if (p->num_engines[i] > 0 || EngineHasReplacementForPlayer(p, i)) {
 
					if (sel[0] == count) selected_id[0] = i;
 
					count++;
 
				}
 
			}
 

	
 
			if (selected_id[0] != INVALID_ENGINE) {
 
				byte subtype = AircraftVehInfo(selected_id[0])->subtype;
 

	
 
				for (i = AIRCRAFT_ENGINES_INDEX; i < AIRCRAFT_ENGINES_INDEX + NUM_AIRCRAFT_ENGINES; i++) {
 
					if (HASBIT(GetEngine(i)->player_avail, _local_player) &&
 
							(subtype & AIR_CTOL) == (AircraftVehInfo(i)->subtype & AIR_CTOL)) {
 
						if (sel[1] == count2) selected_id[1] = i;
 
@@ -641,29 +640,29 @@ static void DrawEngineArrayInReplaceWind
 
		}
 

	
 
		case VEH_Road: {
 
			int num = NUM_ROAD_ENGINES;
 
			const Engine* e = GetEngine(ROAD_ENGINES_INDEX);
 
			EngineID engine_id = ROAD_ENGINES_INDEX;
 
			byte cargo;
 

	
 
			if (selected_id[0] >= ROAD_ENGINES_INDEX && selected_id[0] < SHIP_ENGINES_INDEX) {
 
				cargo = RoadVehInfo(selected_id[0])->cargo_type;
 

	
 
				do {
 
					if (_player_num_engines[engine_id] > 0 || EngineHasReplacementForPlayer(p, engine_id)) {
 
					if (p->num_engines[engine_id] > 0 || EngineHasReplacementForPlayer(p, engine_id)) {
 
						if (IS_INT_INSIDE(--pos, -w->vscroll.cap, 0)) {
 
							DrawString(x+59, y+2, GetCustomEngineName(engine_id), sel[0]==0 ? 0xC : 0x10);
 
							DrawRoadVehEngine(x+29, y+6, engine_id, _player_num_engines[engine_id] > 0 ? GetEnginePalette(engine_id, _local_player) : PALETTE_CRASH);
 
							SetDParam(0, _player_num_engines[engine_id]);
 
							DrawRoadVehEngine(x+29, y+6, engine_id, p->num_engines[engine_id] > 0 ? GetEnginePalette(engine_id, _local_player) : PALETTE_CRASH);
 
							SetDParam(0, p->num_engines[engine_id]);
 
							DrawStringRightAligned(213, y+5, STR_TINY_BLACK, 0);
 
							y += 14;
 
						}
 
					sel[0]--;
 
					}
 

	
 
					if (RoadVehInfo(engine_id)->cargo_type == cargo && HASBIT(e->player_avail, _local_player)) {
 
						if (IS_INT_INSIDE(--pos2, -w->vscroll.cap, 0) && RoadVehInfo(engine_id)->cargo_type == cargo) {
 
							DrawString(x2+59, y2+2, GetCustomEngineName(engine_id), sel[1]==0 ? 0xC : 0x10);
 
							DrawRoadVehEngine(x2+29, y2+6, engine_id, GetEnginePalette(engine_id, _local_player));
 
							y2 += 14;
 
						}
 
@@ -676,29 +675,29 @@ static void DrawEngineArrayInReplaceWind
 

	
 
		case VEH_Ship: {
 
			int num = NUM_SHIP_ENGINES;
 
			const Engine* e = GetEngine(SHIP_ENGINES_INDEX);
 
			EngineID engine_id = SHIP_ENGINES_INDEX;
 
			byte cargo, refittable;
 

	
 
			if (selected_id[0] != INVALID_ENGINE) {
 
				cargo = ShipVehInfo(selected_id[0])->cargo_type;
 
				refittable = ShipVehInfo(selected_id[0])->refittable;
 

	
 
				do {
 
					if (_player_num_engines[engine_id] > 0 || EngineHasReplacementForPlayer(p, engine_id)) {
 
					if (p->num_engines[engine_id] > 0 || EngineHasReplacementForPlayer(p, engine_id)) {
 
						if (IS_INT_INSIDE(--pos, -w->vscroll.cap, 0)) {
 
							DrawString(x+75, y+7, GetCustomEngineName(engine_id), sel[0]==0 ? 0xC : 0x10);
 
							DrawShipEngine(x+35, y+10, engine_id, _player_num_engines[engine_id] > 0 ? GetEnginePalette(engine_id, _local_player) : PALETTE_CRASH);
 
							SetDParam(0, _player_num_engines[engine_id]);
 
							DrawShipEngine(x+35, y+10, engine_id, p->num_engines[engine_id] > 0 ? GetEnginePalette(engine_id, _local_player) : PALETTE_CRASH);
 
							SetDParam(0, p->num_engines[engine_id]);
 
							DrawStringRightAligned(213, y+15, STR_TINY_BLACK, 0);
 
							y += 24;
 
						}
 
						sel[0]--;
 
					}
 
					if (selected_id[0] != INVALID_ENGINE) {
 
						if (HASBIT(e->player_avail, _local_player) && ( cargo == ShipVehInfo(engine_id)->cargo_type || refittable & ShipVehInfo(engine_id)->refittable)) {
 
							if (IS_INT_INSIDE(--pos2, -w->vscroll.cap, 0)) {
 
								DrawString(x2+75, y2+7, GetCustomEngineName(engine_id), sel[1]==0 ? 0xC : 0x10);
 
								DrawShipEngine(x2+35, y2+10, engine_id, GetEnginePalette(engine_id, _local_player));
 
								y2 += 24;
 
							}
 
@@ -709,30 +708,30 @@ static void DrawEngineArrayInReplaceWind
 
			}
 
			break;
 
		}   //end of ship
 

	
 
		case VEH_Aircraft: {
 
			if (selected_id[0] != INVALID_ENGINE) {
 
				int num = NUM_AIRCRAFT_ENGINES;
 
				const Engine* e = GetEngine(AIRCRAFT_ENGINES_INDEX);
 
				EngineID engine_id = AIRCRAFT_ENGINES_INDEX;
 
				byte subtype = AircraftVehInfo(selected_id[0])->subtype;
 

	
 
				do {
 
					if (_player_num_engines[engine_id] > 0 || EngineHasReplacementForPlayer(p, engine_id)) {
 
					if (p->num_engines[engine_id] > 0 || EngineHasReplacementForPlayer(p, engine_id)) {
 
						if (sel[0] == 0) selected_id[0] = engine_id;
 
						if (IS_INT_INSIDE(--pos, -w->vscroll.cap, 0)) {
 
							DrawString(x+62, y+7, GetCustomEngineName(engine_id), sel[0]==0 ? 0xC : 0x10);
 
							DrawAircraftEngine(x+29, y+10, engine_id, _player_num_engines[engine_id] > 0 ? GetEnginePalette(engine_id, _local_player) : PALETTE_CRASH);
 
							SetDParam(0, _player_num_engines[engine_id]);
 
							DrawAircraftEngine(x+29, y+10, engine_id, p->num_engines[engine_id] > 0 ? GetEnginePalette(engine_id, _local_player) : PALETTE_CRASH);
 
							SetDParam(0, p->num_engines[engine_id]);
 
							DrawStringRightAligned(213, y+15, STR_TINY_BLACK, 0);
 
							y += 24;
 
						}
 
						sel[0]--;
 
					}
 
					if ((subtype & AIR_CTOL) == (AircraftVehInfo(engine_id)->subtype & AIR_CTOL) &&
 
							HASBIT(e->player_avail, _local_player)) {
 
						if (sel[1] == 0) selected_id[1] = engine_id;
 
						if (IS_INT_INSIDE(--pos2, -w->vscroll.cap, 0)) {
 
							DrawString(x2+62, y2+7, GetCustomEngineName(engine_id), sel[1]==0 ? 0xC : 0x10);
 
							DrawAircraftEngine(x2+29, y2+10, engine_id, GetEnginePalette(engine_id, _local_player));
 
							y2 += 24;
 
@@ -749,58 +748,36 @@ static void DrawEngineArrayInReplaceWind
 

	
 
static void ReplaceVehicleWndProc(Window *w, WindowEvent *e)
 
{
 
	static const StringID _vehicle_type_names[] = {
 
		STR_019F_TRAIN,
 
		STR_019C_ROAD_VEHICLE,
 
		STR_019E_SHIP,
 
		STR_019D_AIRCRAFT
 
	};
 

	
 
	switch (e->event) {
 
		case WE_PAINT: {
 
				const Player *p = GetPlayer(_local_player);
 
				Player *p = GetPlayer(_local_player);
 
				int pos = w->vscroll.pos;
 
				EngineID selected_id[2] = { INVALID_ENGINE, INVALID_ENGINE };
 
				int x = 1;
 
				int y = 15;
 
				int pos2 = w->vscroll2.pos;
 
				int x2 = 1 + 228;
 
				int y2 = 15;
 
				int sel[2];
 
				sel[0] = WP(w,replaceveh_d).sel_index[0];
 
				sel[1] = WP(w,replaceveh_d).sel_index[1];
 

	
 
				{
 
					uint i;
 
					const Vehicle *vehicle;
 
					/* compiler optimisation tend to prefer to keep local variables in the registers instead of global ones,
 
					 * so we cache often used and unchanging variables in local variables to increase the loop speed */
 
					const byte vehicle_type = w->window_number;
 
					const PlayerID player = _local_player;
 

	
 
					for (i = 0; i < lengthof(_player_num_engines); i++) {
 
						_player_num_engines[i] = 0;
 
					}
 
					FOR_ALL_VEHICLES(vehicle) {
 
						if (vehicle->owner == player && vehicle->type == vehicle_type) {
 
							if (vehicle_type == VEH_Aircraft && vehicle->subtype > 2) continue; // plane shadows and helicopter rotors
 
							if (vehicle_type == VEH_Train && (
 
								IsArticulatedPart(vehicle) || // tenders and other articulated parts
 
								(IsMultiheaded(vehicle) && !IsTrainEngine(vehicle)))) continue; // rear parts of multiheaded engines
 
							_player_num_engines[vehicle->engine_type]++;
 
						}
 
					}
 
				}
 

	
 
				SetupScrollStuffForReplaceWindow(w);
 

	
 
				selected_id[0] = WP(w,replaceveh_d).sel_engine[0];
 
				selected_id[1] = WP(w,replaceveh_d).sel_engine[1];
 

	
 
			// sets the selected left item to the top one if it's greater than the number of vehicles in the left side
 

	
 
				if (WP(w,replaceveh_d).count[0] <= sel[0]) {
 
					if (WP(w,replaceveh_d).count[0]) {
 
						sel[0] = 0;
 
						WP(w,replaceveh_d).sel_index[0] = 0;
 
						w->vscroll.pos = 0;
0 comments (0 inline, 0 general)