diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs
index b7e2f744fa..6b80ff6e44 100644
--- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs
+++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs
@@ -42,6 +42,14 @@ namespace osu.Game.Overlays.Mods
         [Cached]
         public Bindable<IReadOnlyList<Mod>> SelectedMods { get; private set; } = new Bindable<IReadOnlyList<Mod>>(Array.Empty<Mod>());
 
+        /// <summary>
+        /// Contains a list of mods which <see cref="ModSelectOverlay"/> should read from to display effects on the selected beatmap.
+        /// </summary>
+        /// <remarks>
+        /// This is different from <see cref="SelectedMods"/> in screens like online-play rooms, where there are required mods activated from the playlist.
+        /// </remarks>
+        public Bindable<IReadOnlyList<Mod>> ActiveMods { get; private set; } = new Bindable<IReadOnlyList<Mod>>(Array.Empty<Mod>());
+
         /// <summary>
         /// Contains a dictionary with the current <see cref="ModState"/> of all mods applicable for the current ruleset.
         /// </summary>
@@ -313,22 +321,29 @@ namespace osu.Game.Overlays.Mods
             if (AllowCustomisation)
                 ((IBindable<IReadOnlyList<Mod>>)modSettingsArea.SelectedMods).BindTo(SelectedMods);
 
-            SelectedMods.BindValueChanged(_ =>
+            SelectedMods.BindValueChanged(mods =>
             {
-                UpdateOverlayInformation(SelectedMods.Value);
+                var newMods = ActiveMods.Value.Except(mods.OldValue).Concat(mods.NewValue).ToList();
+                ActiveMods.Value = newMods;
+
                 updateFromExternalSelection();
                 updateCustomisation();
+            }, true);
+
+            ActiveMods.BindValueChanged(_ =>
+            {
+                updateOverlayInformation();
 
                 modSettingChangeTracker?.Dispose();
 
                 if (AllowCustomisation)
                 {
-                    // Importantly, use SelectedMods.Value here (and not the ValueChanged NewValue) as the latter can
+                    // Importantly, use ActiveMods.Value here (and not the ValueChanged NewValue) as the latter can
                     // potentially be stale, due to complexities in the way change trackers work.
                     //
                     // See https://github.com/ppy/osu/pull/23284#issuecomment-1529056988
-                    modSettingChangeTracker = new ModSettingChangeTracker(SelectedMods.Value);
-                    modSettingChangeTracker.SettingChanged += _ => UpdateOverlayInformation(SelectedMods.Value);
+                    modSettingChangeTracker = new ModSettingChangeTracker(ActiveMods.Value);
+                    modSettingChangeTracker.SettingChanged += _ => updateOverlayInformation();
                 }
             }, true);
 
@@ -451,24 +466,24 @@ namespace osu.Game.Overlays.Mods
         }
 
         /// <summary>
-        /// Updates any information displayed on the overlay regarding the effects of the selected mods.
+        /// Updates any information displayed on the overlay regarding the effects of the active mods.
+        /// This reads from <see cref="ActiveMods"/> instead of <see cref="SelectedMods"/>.
         /// </summary>
-        /// <param name="mods">The list of mods to show effect from. This can be overriden to include effect of mods that are not part of the <see cref="SelectedMods"/> bindable (e.g. room mods in multiplayer/playlists).</param>
-        protected virtual void UpdateOverlayInformation(IReadOnlyList<Mod> mods)
+        private void updateOverlayInformation()
         {
             if (rankingInformationDisplay != null)
             {
                 double multiplier = 1.0;
 
-                foreach (var mod in mods)
+                foreach (var mod in ActiveMods.Value)
                     multiplier *= mod.ScoreMultiplier;
 
                 rankingInformationDisplay.ModMultiplier.Value = multiplier;
-                rankingInformationDisplay.Ranked.Value = mods.All(m => m.Ranked);
+                rankingInformationDisplay.Ranked.Value = ActiveMods.Value.All(m => m.Ranked);
             }
 
             if (beatmapAttributesDisplay != null)
-                beatmapAttributesDisplay.Mods.Value = mods;
+                beatmapAttributesDisplay.Mods.Value = ActiveMods.Value;
         }
 
         private void updateCustomisation()
diff --git a/osu.Game/Screens/OnlinePlay/Match/RoomModSelectOverlay.cs b/osu.Game/Screens/OnlinePlay/Match/RoomModSelectOverlay.cs
index db7cfe980c..d3fd6de911 100644
--- a/osu.Game/Screens/OnlinePlay/Match/RoomModSelectOverlay.cs
+++ b/osu.Game/Screens/OnlinePlay/Match/RoomModSelectOverlay.cs
@@ -1,7 +1,6 @@
 // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
 // See the LICENCE file in the repository root for full licence text.
 
-using System.Collections.Generic;
 using System.Diagnostics;
 using System.Linq;
 using osu.Framework.Allocation;
@@ -10,7 +9,6 @@ using osu.Game.Online.Rooms;
 using osu.Game.Overlays;
 using osu.Game.Overlays.Mods;
 using osu.Game.Rulesets;
-using osu.Game.Rulesets.Mods;
 
 namespace osu.Game.Screens.OnlinePlay.Match
 {
@@ -22,8 +20,6 @@ namespace osu.Game.Screens.OnlinePlay.Match
         [Resolved]
         private RulesetStore rulesets { get; set; } = null!;
 
-        private readonly List<Mod> roomMods = new List<Mod>();
-
         public RoomModSelectOverlay()
             : base(OverlayColourScheme.Plum)
         {
@@ -33,22 +29,17 @@ namespace osu.Game.Screens.OnlinePlay.Match
         {
             base.LoadComplete();
 
-            selectedItem.BindValueChanged(_ =>
+            selectedItem.BindValueChanged(v =>
             {
-                roomMods.Clear();
-
-                if (selectedItem.Value is PlaylistItem item)
+                if (v.NewValue is PlaylistItem item)
                 {
                     var rulesetInstance = rulesets.GetRuleset(item.RulesetID)?.CreateInstance();
                     Debug.Assert(rulesetInstance != null);
-                    roomMods.AddRange(item.RequiredMods.Select(m => m.ToMod(rulesetInstance)));
+                    ActiveMods.Value = item.RequiredMods.Select(m => m.ToMod(rulesetInstance)).Concat(SelectedMods.Value).ToList();
                 }
-
-                SelectedMods.TriggerChange();
-            });
+                else
+                    ActiveMods.Value = SelectedMods.Value;
+            }, true);
         }
-
-        protected override void UpdateOverlayInformation(IReadOnlyList<Mod> mods)
-            => base.UpdateOverlayInformation(roomMods.Concat(mods).ToList());
     }
 }