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
 
@@ -393,12 +393,13 @@ int32 CmdBuildAircraft(TileIndex tile, u
 
			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
openttd.c
Show inline comments
 
@@ -1453,12 +1453,26 @@ bool AfterLoadGame(void)
 
	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.h
Show inline comments
 
@@ -191,12 +191,13 @@ typedef struct Player {
 
	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);
players.c
Show inline comments
 
@@ -517,12 +517,14 @@ Player *DoStartupNewPlayer(bool is_ai)
 
	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
roadveh_cmd.c
Show inline comments
 
@@ -188,12 +188,13 @@ int32 CmdBuildRoadVeh(TileIndex tile, ui
 

	
 
		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
ship_cmd.c
Show inline comments
 
@@ -911,12 +911,13 @@ int32 CmdBuildShip(TileIndex tile, uint3
 
		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
train_cmd.c
Show inline comments
 
@@ -632,12 +632,13 @@ static int32 CmdBuildRailWagon(EngineID 
 
			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
 
			}
 
		}
 
@@ -812,12 +813,13 @@ int32 CmdBuildRailVehicle(TileIndex tile
 
			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
 
			}
vehicle.c
Show inline comments
 
@@ -532,14 +532,34 @@ uint CountVehiclesInChain(const Vehicle*
 
{
 
	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);
vehicle.h
Show inline comments
 
@@ -252,12 +252,13 @@ Vehicle *ForceAllocateSpecialVehicle(voi
 
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);
vehicle_gui.c
Show inline comments
 
@@ -46,13 +46,12 @@ typedef 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;
 
@@ -440,13 +439,13 @@ static void train_engine_drawing_loop(in
 
	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;
 

	
 
@@ -467,16 +466,16 @@ static void train_engine_drawing_loop(in
 
		}
 

	
 
		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;
 
	}
 
@@ -507,13 +506,13 @@ static void SetupScrollStuffForReplaceWi
 
				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++;
 
@@ -522,13 +521,13 @@ static void SetupScrollStuffForReplaceWi
 
			}
 
			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
 
@@ -544,13 +543,13 @@ static void SetupScrollStuffForReplaceWi
 
			}
 
			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) {
 
@@ -570,13 +569,13 @@ static void SetupScrollStuffForReplaceWi
 
			}
 
			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) {
 
@@ -647,17 +646,17 @@ static void DrawEngineArrayInReplaceWind
 
			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]--;
 
					}
 

	
 
@@ -682,17 +681,17 @@ static void DrawEngineArrayInReplaceWind
 

	
 
			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) {
 
@@ -715,18 +714,18 @@ static void DrawEngineArrayInReplaceWind
 
				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) &&
 
@@ -755,46 +754,24 @@ static void ReplaceVehicleWndProc(Window
 
		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
0 comments (0 inline, 0 general)