summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/autoreplace_cmd.cpp2
-rw-r--r--src/elrail.cpp2
-rw-r--r--src/lang/english.txt1
-rw-r--r--src/newgrf_config.h1
-rw-r--r--src/openttd.cpp2
-rw-r--r--src/rail_cmd.cpp2
-rw-r--r--src/saveload/afterload.cpp2
-rw-r--r--src/saveload/vehicle_sl.cpp4
-rw-r--r--src/settings.cpp2
-rw-r--r--src/train.h18
-rw-r--r--src/train_cmd.cpp41
-rw-r--r--src/vehicle.cpp2
-rw-r--r--src/vehicle_cmd.cpp2
13 files changed, 54 insertions, 27 deletions
diff --git a/src/autoreplace_cmd.cpp b/src/autoreplace_cmd.cpp
index 27d6fddcd..2e13caffb 100644
--- a/src/autoreplace_cmd.cpp
+++ b/src/autoreplace_cmd.cpp
@@ -160,7 +160,7 @@ static void TransferCargo(Vehicle *old_veh, Vehicle *new_head, bool part_of_chai
}
/* Update train weight etc., the old vehicle will be sold anyway */
- if (part_of_chain && new_head->type == VEH_TRAIN) Train::From(new_head)->ConsistChanged(true);
+ if (part_of_chain && new_head->type == VEH_TRAIN) Train::From(new_head)->ConsistChanged(CCF_LOADUNLOAD);
}
/**
diff --git a/src/elrail.cpp b/src/elrail.cpp
index 80f095d80..a43183792 100644
--- a/src/elrail.cpp
+++ b/src/elrail.cpp
@@ -627,7 +627,7 @@ bool SettingsDisableElrail(int32 p1)
FOR_ALL_TRAINS(t) {
/* power and acceleration is cached only for front engines */
if (t->IsFrontEngine()) {
- t->ConsistChanged(true);
+ t->ConsistChanged(CCF_TRACK);
}
}
diff --git a/src/lang/english.txt b/src/lang/english.txt
index ee2827663..52fa8c228 100644
--- a/src/lang/english.txt
+++ b/src/lang/english.txt
@@ -2877,6 +2877,7 @@ STR_NEWGRF_LIST_MISSING :{RED}Missing fi
STR_NEWGRF_BROKEN :{WHITE}Behaviour of NewGRF '{0:RAW_STRING}' is likely to cause desyncs and/or crashes
STR_NEWGRF_BROKEN_POWERED_WAGON :{WHITE}It changed powered-wagon state for '{1:ENGINE}' when not inside a depot
STR_NEWGRF_BROKEN_VEHICLE_LENGTH :{WHITE}It changed vehicle length for '{1:ENGINE}' when not inside a depot
+STR_NEWGRF_BROKEN_CAPACITY :{WHITE}It changed vehicle capacity for '{1:ENGINE}' when not inside a depot or refitting
STR_BROKEN_VEHICLE_LENGTH :{WHITE}Train '{VEHICLE}' belonging to '{COMPANY}' has invalid length. It is probably caused by problems with NewGRFs. Game may desync or crash
STR_NEWGRF_BUGGY :{WHITE}NewGRF '{0:RAW_STRING}' provides incorrect information
diff --git a/src/newgrf_config.h b/src/newgrf_config.h
index ed35c144e..906f9620d 100644
--- a/src/newgrf_config.h
+++ b/src/newgrf_config.h
@@ -46,6 +46,7 @@ enum GRFBugs {
GBUG_VEH_REFIT, ///< Articulated vehicles carry different cargoes resp. are differently refittable than specified in purchase list
GBUG_VEH_POWERED_WAGON, ///< Powered wagon changed poweredness state when not inside a depot
GBUG_UNKNOWN_CB_RESULT, ///< A callback returned an unknown/invalid result
+ GBUG_VEH_CAPACITY, ///< Capacity of vehicle changes when not refitting or arranging
};
/** Status of post-gameload GRF compatibility check */
diff --git a/src/openttd.cpp b/src/openttd.cpp
index 7a3f84eea..6092805eb 100644
--- a/src/openttd.cpp
+++ b/src/openttd.cpp
@@ -1276,7 +1276,7 @@ static void CheckCaches()
}
switch (v->type) {
- case VEH_TRAIN: Train::From(v)->ConsistChanged(true); break;
+ case VEH_TRAIN: Train::From(v)->ConsistChanged(CCF_TRACK); break;
case VEH_ROAD: RoadVehUpdateCache(RoadVehicle::From(v)); break;
case VEH_AIRCRAFT: UpdateAircraftCache(Aircraft::From(v)); break;
case VEH_SHIP: Ship::From(v)->UpdateCache(); break;
diff --git a/src/rail_cmd.cpp b/src/rail_cmd.cpp
index 61adedfa2..4dd4659bb 100644
--- a/src/rail_cmd.cpp
+++ b/src/rail_cmd.cpp
@@ -1718,7 +1718,7 @@ CommandCost CmdConvertRail(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3
if (flags & DC_EXEC) {
/* Railtype changed, update trains as when entering different track */
for (Train **v = affected_trains.Begin(); v != affected_trains.End(); v++) {
- (*v)->ConsistChanged(true);
+ (*v)->ConsistChanged(CCF_TRACK);
}
}
diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp
index ab34a0c07..87754d6b5 100644
--- a/src/saveload/afterload.cpp
+++ b/src/saveload/afterload.cpp
@@ -1221,7 +1221,7 @@ bool AfterLoadGame()
}
FOR_ALL_TRAINS(v) {
- if (v->IsFrontEngine() || v->IsFreeWagon()) v->ConsistChanged(true);
+ if (v->IsFrontEngine() || v->IsFreeWagon()) v->ConsistChanged(CCF_TRACK);
}
}
diff --git a/src/saveload/vehicle_sl.cpp b/src/saveload/vehicle_sl.cpp
index 3ee6ce99c..ad8ef0831 100644
--- a/src/saveload/vehicle_sl.cpp
+++ b/src/saveload/vehicle_sl.cpp
@@ -376,7 +376,7 @@ void AfterLoadVehicles(bool part_of_load)
Train *t = Train::From(v);
if (t->IsFrontEngine() || t->IsFreeWagon()) {
t->gcache.last_speed = t->cur_speed; // update displayed train speed
- t->ConsistChanged(false);
+ t->ConsistChanged(CCF_SAVELOAD);
}
break;
}
@@ -547,7 +547,7 @@ void FixupTrainLengths()
}
/* Update all cached properties after moving the vehicle chain around. */
- Train::From(v)->ConsistChanged(true);
+ Train::From(v)->ConsistChanged(CCF_TRACK);
}
}
}
diff --git a/src/settings.cpp b/src/settings.cpp
index 825e3cbca..970c169b4 100644
--- a/src/settings.cpp
+++ b/src/settings.cpp
@@ -869,7 +869,7 @@ static bool UpdateConsists(int32 p1)
Train *t;
FOR_ALL_TRAINS(t) {
/* Update the consist of all trains so the maximum speed is set correctly. */
- if (t->IsFrontEngine() || t->IsFreeWagon()) t->ConsistChanged(true);
+ if (t->IsFrontEngine() || t->IsFreeWagon()) t->ConsistChanged(CCF_TRACK);
}
InvalidateWindowClassesData(WC_BUILD_VEHICLE, 0);
return true;
diff --git a/src/train.h b/src/train.h
index 8f4bc2a9b..280d59ebd 100644
--- a/src/train.h
+++ b/src/train.h
@@ -12,6 +12,8 @@
#ifndef TRAIN_H
#define TRAIN_H
+#include "core/enum_type.hpp"
+
#include "newgrf_engine.h"
#include "cargotype.h"
#include "rail.h"
@@ -41,6 +43,20 @@ enum TrainForceProceeding {
};
typedef SimpleTinyEnumT<TrainForceProceeding, byte> TrainForceProceedingByte;
+/** Flags for Train::ConsistChanged */
+enum ConsistChangeFlags {
+ CCF_LENGTH = 0x01, ///< Allow vehicles to change length.
+ CCF_CAPACITY = 0x02, ///< Allow vehicles to change capacity.
+
+ CCF_TRACK = 0, ///< Valid changes while vehicle is driving, and possibly changing tracks.
+ CCF_LOADUNLOAD = 0, ///< Valid changes while vehicle is loading/unloading.
+ CCF_AUTOREFIT = CCF_CAPACITY, ///< Valid changes for autorefitting in stations.
+ CCF_REFIT = CCF_LENGTH | CCF_CAPACITY, ///< Valid changes for refitting in a depot.
+ CCF_ARRANGE = CCF_LENGTH | CCF_CAPACITY, ///< Valid changes for arranging the consist in a depot.
+ CCF_SAVELOAD = CCF_LENGTH, ///< Valid changes when loading a savegame. (Everything that is not stored in the save.)
+};
+DECLARE_ENUM_AS_BIT_SET(ConsistChangeFlags)
+
byte FreightWagonMult(CargoID cargo);
void CheckTrainsLengths();
@@ -115,7 +131,7 @@ struct Train FINAL : public GroundVehicle<Train, VEH_TRAIN> {
int GetCurveSpeedLimit() const;
- void ConsistChanged(bool same_length);
+ void ConsistChanged(ConsistChangeFlags allowed_changes);
int UpdateSpeed();
diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp
index 4e9ab2a15..0198ac58c 100644
--- a/src/train_cmd.cpp
+++ b/src/train_cmd.cpp
@@ -122,9 +122,9 @@ void CheckTrainsLengths()
* Recalculates the cached stuff of a train. Should be called each time a vehicle is added
* to/removed from the chain, and when the game is loaded.
* Note: this needs to be called too for 'wagon chains' (in the depot, without an engine)
- * @param same_length should length of vehicles stay the same?
+ * @param allowed_changes Stuff that is allowed to change.
*/
-void Train::ConsistChanged(bool same_length)
+void Train::ConsistChanged(ConsistChangeFlags allowed_changes)
{
uint16 max_speed = UINT16_MAX;
@@ -207,8 +207,15 @@ void Train::ConsistChanged(bool same_length)
}
uint16 new_cap = e_u->DetermineCapacity(u);
- u->refit_cap = min(new_cap, u->refit_cap);
- u->cargo_cap = new_cap;
+ if (allowed_changes & CCF_CAPACITY) {
+ /* Update vehicle capacity. */
+ if (u->cargo_cap > new_cap) u->cargo.Truncate(new_cap);
+ u->refit_cap = min(new_cap, u->refit_cap);
+ u->cargo_cap = new_cap;
+ } else {
+ /* Verify capacity hasn't changed. */
+ if (new_cap != u->cargo_cap) ShowNewGrfVehicleError(u->engine_type, STR_NEWGRF_BROKEN, STR_NEWGRF_BROKEN_CAPACITY, GBUG_VEH_CAPACITY, true);
+ }
u->vcache.cached_cargo_age_period = GetVehicleProperty(u, PROP_TRAIN_CARGO_AGE_PERIOD, e_u->info.cargo_age_period);
/* check the vehicle length (callback) */
@@ -227,11 +234,13 @@ void Train::ConsistChanged(bool same_length)
if (veh_len == CALLBACK_FAILED) veh_len = rvi_u->shorten_factor;
veh_len = VEHICLE_LENGTH - Clamp(veh_len, 0, VEHICLE_LENGTH - 1);
- /* verify length hasn't changed */
- if (same_length && veh_len != u->gcache.cached_veh_length) VehicleLengthChanged(u);
-
- /* update vehicle length? */
- if (!same_length) u->gcache.cached_veh_length = veh_len;
+ if (allowed_changes & CCF_LENGTH) {
+ /* Update vehicle length. */
+ u->gcache.cached_veh_length = veh_len;
+ } else {
+ /* Verify length hasn't changed. */
+ if (veh_len != u->gcache.cached_veh_length) VehicleLengthChanged(u);
+ }
this->gcache.cached_total_length += u->gcache.cached_veh_length;
this->InvalidateNewGRFCache();
@@ -632,7 +641,7 @@ static CommandCost CmdBuildRailWagon(TileIndex tile, DoCommandFlag flags, const
_new_vehicle_id = v->index;
VehicleUpdatePosition(v);
- v->First()->ConsistChanged(false);
+ v->First()->ConsistChanged(CCF_ARRANGE);
UpdateTrainGroupID(v->First());
CheckConsistencyOfArticulatedVehicle(v);
@@ -774,7 +783,7 @@ CommandCost CmdBuildRailVehicle(TileIndex tile, DoCommandFlag flags, const Engin
AddArticulatedParts(v);
}
- v->ConsistChanged(false);
+ v->ConsistChanged(CCF_ARRANGE);
UpdateTrainGroupID(v);
if (!HasBit(data, 0) && !(flags & DC_AUTOREPLACE)) { // check if the cars should be added to the new vehicle
@@ -1120,7 +1129,7 @@ static void NormaliseTrainHead(Train *head)
if (head == NULL) return;
/* Tell the 'world' the train changed. */
- head->ConsistChanged(false);
+ head->ConsistChanged(CCF_ARRANGE);
UpdateTrainGroupID(head);
/* Not a front engine, i.e. a free wagon chain. No need to do more. */
@@ -1824,7 +1833,7 @@ void ReverseTrainDirection(Train *v)
ClrBit(v->flags, VRF_REVERSING);
/* recalculate cached data */
- v->ConsistChanged(true);
+ v->ConsistChanged(CCF_TRACK);
/* update all images */
for (Train *u = v; u != NULL; u = u->Next()) u->UpdateViewport(false, false);
@@ -1908,7 +1917,7 @@ CommandCost CmdReverseTrainDirection(TileIndex tile, DoCommandFlag flags, uint32
if (flags & DC_EXEC) {
ToggleBit(v->flags, VRF_REVERSE_DIRECTION);
- front->ConsistChanged(false);
+ front->ConsistChanged(CCF_ARRANGE);
SetWindowDirty(WC_VEHICLE_DEPOT, front->tile);
SetWindowDirty(WC_VEHICLE_DETAILS, front->index);
SetWindowDirty(WC_VEHICLE_VIEW, front->index);
@@ -3271,7 +3280,7 @@ bool TrainController(Train *v, Vehicle *nomove, bool reverse)
v->tile = gp.new_tile;
if (GetTileRailType(gp.new_tile) != GetTileRailType(gp.old_tile)) {
- v->First()->ConsistChanged(true);
+ v->First()->ConsistChanged(CCF_TRACK);
}
v->track = chosen_track;
@@ -3437,7 +3446,7 @@ static void DeleteLastWagon(Train *v)
if (first != v) {
/* Recalculate cached train properties */
- first->ConsistChanged(false);
+ first->ConsistChanged(CCF_ARRANGE);
/* Update the depot window if the first vehicle is in depot -
* if v == first, then it is updated in PreDestructor() */
if (first->track == TRACK_BIT_DEPOT) {
diff --git a/src/vehicle.cpp b/src/vehicle.cpp
index 2037da7cd..ceb345f46 100644
--- a/src/vehicle.cpp
+++ b/src/vehicle.cpp
@@ -1355,7 +1355,7 @@ void VehicleEnterDepot(Vehicle *v)
t->wait_counter = 0;
t->force_proceed = TFP_NONE;
ClrBit(t->flags, VRF_TOGGLE_REVERSE);
- t->ConsistChanged(true);
+ t->ConsistChanged(CCF_ARRANGE);
break;
}
diff --git a/src/vehicle_cmd.cpp b/src/vehicle_cmd.cpp
index f45bd4b5a..78c62d20a 100644
--- a/src/vehicle_cmd.cpp
+++ b/src/vehicle_cmd.cpp
@@ -463,7 +463,7 @@ CommandCost CmdRefitVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint
/* Update the cached variables */
switch (v->type) {
case VEH_TRAIN:
- Train::From(front)->ConsistChanged(auto_refit);
+ Train::From(front)->ConsistChanged(auto_refit ? CCF_AUTOREFIT : CCF_REFIT);
break;
case VEH_ROAD:
RoadVehUpdateCache(RoadVehicle::From(front), auto_refit);