Skip to main content
Mods (modifiers) are gameplay modifications that change how the game behaves. They can increase difficulty, add fun mechanics, or provide assistance. The mod system is highly extensible and supports custom configurations.

Mod Base Class

All mods inherit from the Mod abstract class:
public abstract class Mod : IMod, IEquatable<Mod>, IDeepCloneable<Mod>
{
    public abstract string Name { get; }
    public abstract string Acronym { get; }
    public abstract LocalisableString Description { get; }
    public abstract double ScoreMultiplier { get; }
    public virtual ModType Type => ModType.Fun;
}

Core Mod Properties

  • Name: Full mod name (e.g., “Hard Rock”)
  • Acronym: Short abbreviation (e.g., “HR”)
  • Description: What the mod does
  • Icon: Visual icon for the mod
public abstract string Name { get; }
public abstract string Acronym { get; }
public virtual IconUsage? Icon => null;
  • ScoreMultiplier: How the mod affects score (e.g., 1.06 for +6%)
  • Type: Category of the mod (DifficultyIncrease, DifficultyReduction, etc.)
  • Ranked: Whether scores with this mod count for ranking
public abstract double ScoreMultiplier { get; }
public virtual ModType Type => ModType.Fun;
public virtual bool Ranked => false;
  • UserPlayable: Can users select this mod?
  • ValidForMultiplayer: Can be used in multiplayer?
  • ValidForMultiplayerAsFreeMod: Available as free mod choice?
  • HasImplementation: Is the mod fully implemented?
public virtual bool UserPlayable => true;
public virtual bool ValidForMultiplayer => true;
public virtual bool ValidForMultiplayerAsFreeMod => true;
public virtual bool HasImplementation => this is IApplicableMod;

Mod Types

Mods are categorized by their purpose:

Mod Categories

  • DifficultyReduction: Makes the game easier (e.g., Easy, No Fail)
  • DifficultyIncrease: Makes the game harder (e.g., Hard Rock, Hidden)
  • Automation: Auto-play mods (e.g., Autoplay, Cinema)
  • Conversion: Changes game mode mechanics
  • Fun: Entertainment mods that don’t affect difficulty significantly
  • System: Internal system mods

Common Mods

Here are some of the standard mods available:

Difficulty Reduction Mods

Reduces overall difficulty:
  • Larger hit objects
  • More lenient timing
  • Slower approach rate
  • Extra lives (in some implementations)
public class ModEasy : Mod
{
    public override string Acronym => "EZ";
    public override double ScoreMultiplier => 0.5;
}
Prevents failing - health never reaches zero.Score multiplier: 0.5x
Slows down the beatmap to 75% speed.
public class ModHalfTime : ModTimeAdjust
{
    public override string Acronym => "HT";
    public override double ScoreMultiplier => 0.3;
}

Difficulty Increase Mods

Increases difficulty by:
  • Smaller hit objects (higher CS)
  • Stricter timing (higher OD)
  • Faster approach (higher AR)
  • Faster drain (higher HP)
  • Flips the playfield vertically
public class ModHardRock : Mod
{
    public override string Acronym => "HR";
    public override double ScoreMultiplier => 1.06;
}
Hit objects fade out before they need to be hit.Score multiplier: 1.06x
Speeds up the beatmap to 150% speed.
public class ModDoubleTime : ModTimeAdjust
{
    public override string Acronym => "DT";
    public override double ScoreMultiplier => 1.12;
}
Restricts vision to a small circle around the cursor.Score multiplier: 1.12x

Special Mods

Unique Mechanics

Auto-moves cursor or auto-clicks (depending on mode).Score multiplier: 0.0x (unranked)
Watch a beatmap with background dim disabled.
public class ModCinema : ModAutoplay
{
    public override string Acronym => "CN";
}
Flips the playfield horizontally.
public class ModMirror : Mod
{
    public override string Acronym => "MR";
    public override double ScoreMultiplier => 1.0;
}

Mod Settings

Many mods have configurable settings:
public virtual IEnumerable<(LocalisableString setting, LocalisableString value)> SettingDescription
{
    get
    {
        foreach ((SettingSourceAttribute attr, PropertyInfo property) in this.GetOrderedSettingsSourceProperties())
        {
            var bindable = (IBindable)property.GetValue(this)!;
            if (bindable.IsDefault)
                continue;
                
            yield return (attr.Label, GetSettingTooltipText(bindable));
        }
    }
}

Configurable Mods

Allows manual adjustment of all difficulty parameters:
public class ModDifficultyAdjust : Mod
{
    public BindableFloat DrainRate { get; set; }
    public BindableFloat CircleSize { get; set; }
    public BindableFloat ApproachRate { get; set; }
    public BindableFloat OverallDifficulty { get; set; }
}
Adjusts playback speed based on performance:
public class ModAdaptiveSpeed : Mod
{
    public BindableFloat InitialRate { get; set; }
    public BindableFloat AdjustPitch { get; set; }
}
Configurable sight radius:
public class ModFlashlight : Mod
{
    public BindableFloat SizeMultiplier { get; set; }
    public BindableBool ComboBasedSize { get; set; }
}

Setting Management

Settings API

// Check if mod uses default settings
public virtual bool UsesDefaultConfiguration => 
    SettingsBindables.All(s => s.IsDefault);

// Reset all settings to defaults
public virtual void ResetSettingsToDefaults() => 
    CopyFrom((Mod)Activator.CreateInstance(GetType())!);

// Access all settings
internal IEnumerable<IBindable> SettingsBindables => 
    SettingsMap.OrderBy(pair => pair.Key).Select(pair => pair.Value);

Mod Compatibility

Mods can specify incompatibilities:
public virtual Type[] IncompatibleMods => Array.Empty<Type>();

Incompatibility Examples

  • Easy is incompatible with Hard Rock
  • Double Time is incompatible with Half Time
  • No Fail is incompatible with Perfect
  • Autoplay is incompatible with Relax
Attempting to enable incompatible mods together will result in one being automatically disabled.

Mod Application Interfaces

Mods implement various interfaces to apply their effects:
Modifies difficulty settings:
public interface IApplicableToDifficulty : IApplicableMod
{
    void ReadFromDifficulty(IBeatmapDifficultyInfo difficulty);
    void ApplyToDifficulty(BeatmapDifficulty difficulty);
}
Changes playback rate:
public interface IApplicableToRate : IApplicableMod
{
    BindableNumber<double> SpeedChange { get; }
}
Modifies individual hit objects:
public interface IApplicableToDrawableHitObject : IApplicableMod
{
    void ApplyToDrawableHitObject(DrawableHitObject drawable);
}
Changes score calculation:
public interface IApplicableToScoreProcessor : IApplicableMod
{
    void ApplyToScoreProcessor(ScoreProcessor scoreProcessor);
}
Modifies health drain/recovery:
public interface IApplicableToHealthProcessor : IApplicableMod
{
    void ApplyToHealthProcessor(HealthProcessor healthProcessor);
}

Mod Cloning and Copying

Mods can be cloned and have settings copied:
public virtual Mod DeepClone()
{
    var result = (Mod)Activator.CreateInstance(GetType())!;
    result.CopyFrom(this);
    return result;
}

public void CopyFrom(Mod source)
{
    if (source.GetType() != GetType())
        throw new ArgumentException($"Expected mod of type {GetType()}, got {source.GetType()}.");

    foreach (var (_, property) in this.GetSettingsSourceProperties())
    {
        var targetBindable = (IBindable)property.GetValue(this)!;
        var sourceBindable = (IBindable)property.GetValue(source)!;
        CopyAdjustedSetting(targetBindable, sourceBindable);
    }
}
Copying common settings across mods allows preserving user preferences when switching rulesets:
public void CopyCommonSettingsFrom(Mod source)
{
    // Only copies settings that exist in both mods
}

Mod Equality

Mods are equal if they’re the same type with the same settings:
public bool Equals(Mod? other)
{
    if (ReferenceEquals(null, other)) return false;
    if (ReferenceEquals(this, other)) return true;

    return GetType() == other.GetType() &&
           SettingsBindables.SequenceEqual(other.SettingsBindables, 
                                          ModSettingsEqualityComparer.Default);
}

Special Mod Features

Accuracy Challenge

ModAccuracyChallenge

Fails the play if accuracy drops below a threshold:
public class ModAccuracyChallenge : ModFailCondition
{
    public BindableNumber<double> MinimumAccuracy { get; set; }
}

Barrel Roll

ModBarrelRoll

Rotates the entire playfield:
public class ModBarrelRoll : Mod
{
    public BindableNumber<float> SpinSpeed { get; set; }
    public BindableNumber<int> Direction { get; set; }
}

Muted

ModMuted

Mutes hit sounds and/or music:
public class ModMuted : Mod, IApplicableToAudio
{
    public BindableBool MuteHitSounds { get; set; }
    public BindableBool MuteMusic { get; set; }
}

Mod in Multiplayer

Mods can be:
  • Required: All players must use them
  • Allowed: Players can optionally enable them
  • Free Mods: Players choose their own mods
public virtual bool ValidForMultiplayer => true;
public virtual bool ValidForMultiplayerAsFreeMod => true;
Some mods are not valid for multiplayer competitive play:
  • Autoplay
  • Cinema
  • Relax
  • Any mod with ValidForMultiplayer = false

Creating Custom Mods

To create a custom mod:
1

Inherit from Mod

public class MyCustomMod : Mod
{
    public override string Name => "My Mod";
    public override string Acronym => "MM";
    public override LocalisableString Description => "Does something cool";
    public override double ScoreMultiplier => 1.0;
}
2

Implement Application Interfaces

Add interfaces for what the mod affects:
public class MyCustomMod : Mod, IApplicableToDrawableHitObject
{
    public void ApplyToDrawableHitObject(DrawableHitObject drawable)
    {
        // Modify hit object behavior
    }
}
3

Add Settings (Optional)

[SettingSource("Setting Name", "Description")]
public BindableInt MySetting { get; } = new BindableInt
{
    Default = 5,
    Value = 5,
    MinValue = 1,
    MaxValue = 10
};

Build docs developers (and LLMs) love