summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--aircraft_cmd.c1
-rw-r--r--openttd.c14
-rw-r--r--player.h1
-rw-r--r--players.c2
-rw-r--r--roadveh_cmd.c1
-rw-r--r--ship_cmd.c1
-rw-r--r--train_cmd.c2
-rw-r--r--vehicle.c20
-rw-r--r--vehicle.h1
-rw-r--r--vehicle_gui.c57
10 files changed, 60 insertions, 40 deletions
diff --git a/aircraft_cmd.c b/aircraft_cmd.c
index bac16b525..e9ed824b4 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 a138e0e02..c891105f8 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 f02c801c7..55c13abce 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 27d8b3329..3d7a46876 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 a01e04931..ef3cf4e10 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 ea8f6fdda..371a51e7f 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 205653dbe..73bda7601 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 9b8d1b491..c43e393d8 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 e97f54942..2efd39b04 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 1363ef649..4140a1cbc 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];