diff --git a/src/misc_cmd.cpp b/src/misc_cmd.cpp
index 7102135e99..dd7570d72f 100644
--- a/src/misc_cmd.cpp
+++ b/src/misc_cmd.cpp
@@ -113,6 +113,7 @@ CommandCost CmdSetPlayerColor(TileIndex tile, uint32 flags, uint32 p1, uint32 p2
 			default:
 				break;
 		}
+		ResetVehicleColorMap();
 		MarkWholeScreenDirty();
 	}
 	return CommandCost();
diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp
index 715472f2f2..71dbebb0cb 100644
--- a/src/train_cmd.cpp
+++ b/src/train_cmd.cpp
@@ -41,6 +41,7 @@
 #include "date.h"
 #include "cargotype.h"
 #include "group.h"
+#include "table/sprites.h"
 
 static bool TrainCheckIfLineEnds(Vehicle *v);
 static void TrainController(Vehicle *v, bool update_image);
@@ -176,6 +177,9 @@ void TrainConsistChanged(Vehicle* v)
 		/* Cache wagon override sprite group. NULL is returned if there is none */
 		u->u.rail.cached_override = GetWagonOverrideSpriteSet(u->engine_type, u->cargo_type, u->u.rail.first_engine);
 
+		/* Reset color map */
+		u->colormap = PAL_NONE;
+
 		if (rvi_u->visual_effect != 0) {
 			u->u.rail.cached_vis_effect = rvi_u->visual_effect;
 		} else {
diff --git a/src/vehicle.cpp b/src/vehicle.cpp
index 28fb0e64cc..86151e48ab 100644
--- a/src/vehicle.cpp
+++ b/src/vehicle.cpp
@@ -274,6 +274,7 @@ Vehicle::Vehicle()
 	this->group_id           = DEFAULT_GROUP;
 	this->fill_percent_te_id = INVALID_TE_ID;
 	this->first              = this;
+	this->colormap           = PAL_NONE;
 }
 
 /**
@@ -457,6 +458,12 @@ void ResetVehiclePosHash()
 	memset(_new_vehicle_position_hash, 0, sizeof(_new_vehicle_position_hash));
 }
 
+void ResetVehicleColorMap()
+{
+	Vehicle *v;
+	FOR_ALL_VEHICLES(v) { v->colormap = PAL_NONE; }
+}
+
 void InitializeVehicles()
 {
 	_Vehicle_pool.CleanPool();
@@ -2607,7 +2614,10 @@ const Livery *GetEngineLivery(EngineID engine_type, PlayerID player, EngineID pa
 
 static SpriteID GetEngineColourMap(EngineID engine_type, PlayerID player, EngineID parent_engine_type, const Vehicle *v)
 {
-	SpriteID map = PAL_NONE;
+	SpriteID map = (v != NULL) ? v->colormap : PAL_NONE;
+
+	/* Return cached value if any */
+	if (map != PAL_NONE) return map;
 
 	/* Check if we should use the colour map callback */
 	if (HASBIT(EngInfo(engine_type)->callbackmask, CBM_VEHICLE_COLOUR_REMAP)) {
@@ -2618,7 +2628,11 @@ static SpriteID GetEngineColourMap(EngineID engine_type, PlayerID player, Engine
 			map = GB(callback, 0, 14);
 			/* If bit 14 is set, then the company colours are applied to the
 			 * map else it's returned as-is. */
-			if (!HASBIT(callback, 14)) return map;
+			if (!HASBIT(callback, 14)) {
+				/* Update cache */
+				if (v != NULL) ((Vehicle*)v)->colormap = map;
+				return map;
+			}
 		}
 	}
 
@@ -2631,6 +2645,8 @@ static SpriteID GetEngineColourMap(EngineID engine_type, PlayerID player, Engine
 	map += livery->colour1;
 	if (twocc) map += livery->colour2 * 16;
 
+	/* Update cache */
+	if (v != NULL) ((Vehicle*)v)->colormap = map;
 	return map;
 }
 
diff --git a/src/vehicle.h b/src/vehicle.h
index 7b2b230fc4..dd946900c9 100644
--- a/src/vehicle.h
+++ b/src/vehicle.h
@@ -340,6 +340,8 @@ public:
 	uint32 current_order_time;     ///< How many ticks have passed since this order started.
 	int32 lateness_counter;        ///< How many ticks late (or early if negative) this vehicle is.
 
+	SpriteID colormap; // NOSAVE: cached color mapping
+
 	union {
 		VehicleRail rail;
 		VehicleAir air;
@@ -588,6 +590,7 @@ uint8 CalcPercentVehicleFilled(Vehicle *v, StringID *color);
 void InitializeTrains();
 byte VehicleRandomBits();
 void ResetVehiclePosHash();
+void ResetVehicleColorMap();
 
 bool CanRefitTo(EngineID engine_type, CargoID cid_to);
 CargoID FindFirstRefittableCargo(EngineID engine_type);