(svn r6424) -Codechange: [autoreplace] removed a loop though all vehicles from each time the window is redrawn
authorbjarni
Fri, 08 Sep 2006 10:47:39 +0000
changeset 4574 497540b4a75f
parent 4573 65b6fe8b65b4
child 4575 9a28739233d0
(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
aircraft_cmd.c
openttd.c
player.h
players.c
roadveh_cmd.c
ship_cmd.c
train_cmd.c
vehicle.c
vehicle.h
vehicle_gui.c
--- a/aircraft_cmd.c	Fri Sep 08 03:59:38 2006 +0000
+++ b/aircraft_cmd.c	Fri Sep 08 10:47:39 2006 +0000
@@ -396,6 +396,7 @@
 			w->u.air.state = HRS_ROTOR_STOPPED;
 			VehiclePositionChanged(w);
 		}
+		GetPlayer(_current_player)->num_engines[p1]++;
 
 		InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
 		RebuildVehicleLists();
--- a/openttd.c	Fri Sep 08 03:59:38 2006 +0000
+++ b/openttd.c	Fri Sep 08 10:47:39 2006 +0000
@@ -1456,6 +1456,20 @@
 
 	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)) {
--- a/player.h	Fri Sep 08 03:59:38 2006 +0000
+++ b/player.h	Fri Sep 08 10:47:39 2006 +0000
@@ -194,6 +194,7 @@
 	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);
--- a/players.c	Fri Sep 08 03:59:38 2006 +0000
+++ b/players.c	Fri Sep 08 10:47:39 2006 +0000
@@ -520,6 +520,8 @@
 	if (is_ai && (!_networking || _network_server) && _ai.enabled)
 		AI_StartNewAI(p->index);
 
+	memset(p->num_engines, 0, TOTAL_NUM_ENGINES);
+
 	return p;
 }
 
--- a/roadveh_cmd.c	Fri Sep 08 03:59:38 2006 +0000
+++ b/roadveh_cmd.c	Fri Sep 08 10:47:39 2006 +0000
@@ -191,6 +191,7 @@
 		v->random_bits = VehicleRandomBits();
 
 		VehiclePositionChanged(v);
+		GetPlayer(_current_player)->num_engines[p1]++;
 
 		InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
 		RebuildVehicleLists();
--- a/ship_cmd.c	Fri Sep 08 03:59:38 2006 +0000
+++ b/ship_cmd.c	Fri Sep 08 10:47:39 2006 +0000
@@ -914,6 +914,7 @@
 		v->random_bits = VehicleRandomBits();
 
 		VehiclePositionChanged(v);
+		GetPlayer(_current_player)->num_engines[p1]++;
 
 		InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
 		RebuildVehicleLists();
--- a/train_cmd.c	Fri Sep 08 03:59:38 2006 +0000
+++ b/train_cmd.c	Fri Sep 08 10:47:39 2006 +0000
@@ -635,6 +635,7 @@
 
 			VehiclePositionChanged(v);
 			TrainConsistChanged(GetFirstVehicleInChain(v));
+			GetPlayer(_current_player)->num_engines[engine]++;
 
 			InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
 			if (IsLocalPlayer()) {
@@ -815,6 +816,7 @@
 				NormalizeTrainVehInDepot(v);
 			}
 
+			GetPlayer(_current_player)->num_engines[p1]++;
 			InvalidateWindow(WC_VEHICLE_DEPOT, tile);
 			RebuildVehicleLists();
 			InvalidateWindow(WC_COMPANY, v->owner);
--- a/vehicle.c	Fri Sep 08 03:59:38 2006 +0000
+++ b/vehicle.c	Fri Sep 08 10:47:39 2006 +0000
@@ -535,8 +535,28 @@
 	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);
--- a/vehicle.h	Fri Sep 08 03:59:38 2006 +0000
+++ b/vehicle.h	Fri Sep 08 10:47:39 2006 +0000
@@ -255,6 +255,7 @@
 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);
--- a/vehicle_gui.c	Fri Sep 08 03:59:38 2006 +0000
+++ b/vehicle_gui.c	Fri Sep 08 10:47:39 2006 +0000
@@ -49,7 +49,6 @@
 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;
 
 
@@ -443,7 +442,7 @@
 		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;
@@ -470,10 +469,10 @@
 			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;
@@ -510,7 +509,7 @@
 				// 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++;
 					}
@@ -525,7 +524,7 @@
 
 		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++;
 				}
@@ -547,7 +546,7 @@
 
 		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++;
 				}
@@ -573,7 +572,7 @@
 
 		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++;
 				}
@@ -650,11 +649,11 @@
 				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;
 						}
@@ -685,11 +684,11 @@
 				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;
 						}
@@ -718,12 +717,12 @@
 				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;
 						}
@@ -758,7 +757,7 @@
 
 	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;
@@ -770,28 +769,6 @@
 				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];