From 00a08601c9631282fc921b863843880d30e6fadc Mon Sep 17 00:00:00 2001 From: bjarni Date: Fri, 8 Sep 2006 10:47:39 +0000 Subject: [PATCH] (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 | 1 + openttd.c | 14 +++++++++++++ player.h | 1 + players.c | 2 ++ roadveh_cmd.c | 1 + ship_cmd.c | 1 + train_cmd.c | 2 ++ vehicle.c | 20 ++++++++++++++++++ vehicle.h | 1 + vehicle_gui.c | 57 +++++++++++++++----------------------------------- 10 files changed, 60 insertions(+), 40 deletions(-) diff --git a/aircraft_cmd.c b/aircraft_cmd.c index bac16b5256..e9ed824b4e 100644 --- a/aircraft_cmd.c +++ b/aircraft_cmd.c @@ -396,6 +396,7 @@ int32 CmdBuildAircraft(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) w->u.air.state = HRS_ROTOR_STOPPED; VehiclePositionChanged(w); } + GetPlayer(_current_player)->num_engines[p1]++; InvalidateWindow(WC_VEHICLE_DEPOT, v->tile); RebuildVehicleLists(); diff --git a/openttd.c b/openttd.c index a138e0e021..c891105f89 100644 --- a/openttd.c +++ b/openttd.c @@ -1456,6 +1456,20 @@ bool AfterLoadGame(void) 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)) { diff --git a/player.h b/player.h index f02c801c79..55c13abce6 100644 --- a/player.h +++ b/player.h @@ -194,6 +194,7 @@ typedef struct Player { 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); diff --git a/players.c b/players.c index 27d8b3329c..3d7a468766 100644 --- a/players.c +++ b/players.c @@ -520,6 +520,8 @@ Player *DoStartupNewPlayer(bool is_ai) if (is_ai && (!_networking || _network_server) && _ai.enabled) AI_StartNewAI(p->index); + memset(p->num_engines, 0, TOTAL_NUM_ENGINES); + return p; } diff --git a/roadveh_cmd.c b/roadveh_cmd.c index a01e04931d..ef3cf4e100 100644 --- a/roadveh_cmd.c +++ b/roadveh_cmd.c @@ -191,6 +191,7 @@ int32 CmdBuildRoadVeh(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) v->random_bits = VehicleRandomBits(); VehiclePositionChanged(v); + GetPlayer(_current_player)->num_engines[p1]++; InvalidateWindow(WC_VEHICLE_DEPOT, v->tile); RebuildVehicleLists(); diff --git a/ship_cmd.c b/ship_cmd.c index ea8f6fdda3..371a51e7f9 100644 --- a/ship_cmd.c +++ b/ship_cmd.c @@ -914,6 +914,7 @@ int32 CmdBuildShip(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) v->random_bits = VehicleRandomBits(); VehiclePositionChanged(v); + GetPlayer(_current_player)->num_engines[p1]++; InvalidateWindow(WC_VEHICLE_DEPOT, v->tile); RebuildVehicleLists(); diff --git a/train_cmd.c b/train_cmd.c index 205653dbe4..73bda7601c 100644 --- a/train_cmd.c +++ b/train_cmd.c @@ -635,6 +635,7 @@ static int32 CmdBuildRailWagon(EngineID engine, TileIndex tile, uint32 flags) VehiclePositionChanged(v); TrainConsistChanged(GetFirstVehicleInChain(v)); + GetPlayer(_current_player)->num_engines[engine]++; InvalidateWindow(WC_VEHICLE_DEPOT, v->tile); if (IsLocalPlayer()) { @@ -815,6 +816,7 @@ int32 CmdBuildRailVehicle(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) NormalizeTrainVehInDepot(v); } + GetPlayer(_current_player)->num_engines[p1]++; InvalidateWindow(WC_VEHICLE_DEPOT, tile); RebuildVehicleLists(); InvalidateWindow(WC_COMPANY, v->owner); diff --git a/vehicle.c b/vehicle.c index 9b8d1b4913..c43e393d88 100644 --- a/vehicle.c +++ b/vehicle.c @@ -535,8 +535,28 @@ uint CountVehiclesInChain(const Vehicle* v) 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); diff --git a/vehicle.h b/vehicle.h index e97f54942e..2efd39b043 100644 --- a/vehicle.h +++ b/vehicle.h @@ -255,6 +255,7 @@ 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); diff --git a/vehicle_gui.c b/vehicle_gui.c index 1363ef649f..4140a1cbc2 100644 --- a/vehicle_gui.c +++ b/vehicle_gui.c @@ -49,7 +49,6 @@ static uint32 _internal_name_sorter_id; // internal StringID for default vehicle 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 @@ static void train_engine_drawing_loop(int *x, int *y, int *pos, int *sel, Engine 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 @@ static void train_engine_drawing_loop(int *x, int *y, int *pos, int *sel, Engine 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 @@ static void SetupScrollStuffForReplaceWindow(Window *w) // 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 @@ static void SetupScrollStuffForReplaceWindow(Window *w) 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 @@ static void SetupScrollStuffForReplaceWindow(Window *w) 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 @@ static void SetupScrollStuffForReplaceWindow(Window *w) 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 @@ static void DrawEngineArrayInReplaceWindow(Window *w, int x, int y, int x2, int 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 @@ static void DrawEngineArrayInReplaceWindow(Window *w, int x, int y, int x2, int 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 @@ static void DrawEngineArrayInReplaceWindow(Window *w, int x, int y, int x2, int 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 @@ static void ReplaceVehicleWndProc(Window *w, WindowEvent *e) 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 @@ static void ReplaceVehicleWndProc(Window *w, WindowEvent *e) 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];