Skip to content

Getting Started

QinShenYu edited this page Jun 10, 2026 · 9 revisions

Installation

  1. Install BepInEx 5.x for Scav Prototype if you have not already.
  2. Download ScavLib.dll from the DLL Repository.
  3. Place ScavLib.dll into:
    /BepInEx/plugins/ScavLib.dll
    
  4. Launch the game and open the developer console. Type scavlib status to confirm ScavLib loaded successfully.

Setting Up a Mod Project

1. Add References

In your .csproj, reference both BepInEx.dll and ScavLib.dll. Note that ScavLib's assembly name contains a space (ScavLib API), even though the distributed file is named ScavLib.dll:

<Reference Include="BepInEx">
  <HintPath>path\to\BepInEx\core\BepInEx.dll</HintPath>
  <Private>False</Private>
</Reference>
<Reference Include="ScavLib API">
  <HintPath>path\to\BepInEx\plugins\ScavLib.dll</HintPath>
  <Private>False</Private>
</Reference>

2. Declare the Dependency

Use [BepInDependency] so BepInEx is aware of ScavLib. ScavLib is declared as a soft dependency below — BepInEx will load it first if present, but will not refuse to load your mod if it is missing. If your mod genuinely cannot run without ScavLib, swap SoftDependency for HardDependency.

using BepInEx;
using ScavLib.util;
using ScavLib.event_bus;
using ScavLib.event_bus.events;

[BepInDependency("com.kanisuko.scavlib", BepInDependency.DependencyFlags.SoftDependency)]
[BepInPlugin("com.yourname.yourmod", "YourMod", "1.0.0")]
public class YourPlugin : BaseUnityPlugin
{
    private void Awake()
    {
        // Register event listeners defined in this class.
        EventBus.Register(this);

        Logger.LogInfo("YourMod loaded.");
    }

    // This fires once the game world is fully loaded and Body is safe to access.
    [Subscribe]
    private void OnWorldLoaded(WorldLoadedEvent e)
    {
        GameUtil.Alert("YourMod is active!", important: false);
    }
}

Note on version requirements: The second argument of [BepInDependency] is a DependencyFlags value (SoftDependency / HardDependency), not a version string — it does not express a minimum version. If you need an actual version range check, declare it through ScavLib's own VersionedDependency when registering with ModRegistry (see the ModRegistry page). That check is advisory only: a mismatch logs a warning but does not block load.

3. Namespace Reference

Namespace Contents
ScavLib.util PlayerUtil, SkillUtil, ItemUtil, GameUtil, LimbUtil
ScavLib.event_bus EventBus, BusEvent, [Subscribe]
ScavLib.event_bus.events WorldLoadedEvent, LayerLoadedEvent, WorldUnloadingEvent, WorldDestroyedEvent, ItemPickedUpEvent, ItemDroppedEvent
ScavLib.item CustomItemBuilder, ItemTemplate, CustomItemRegistry, VanillaLimb, VanillaWearSlot
ScavLib.command BaseCommand, CommandRegistry
ScavLib.config ConfigManager
ScavLib.gui.ugui UguiWindowBase, UguiBuilder, UguiTheme, UguiPixelBar
ScavLib.gui.imgui ImguiWindow, ImguiMenuBuilder, ImguiMenuManager
ScavLib.mods ModInfo, ModRegistry, IModLifecycle, ModLifecycleBase, ModSession, VersionedDependency
ScavLib.crafting RecipeBuilder, RecipeCategory
ScavLib.liquid CustomLiquidBuilder
ScavLib.locale LocaleRegistry

Important: When Is It Safe to Access the Player?

BepInEx calls Awake() before any game world exists. Accessing PlayerCamera.main or Body at this point will throw a NullReferenceException.

Always use WorldLoadedEvent as your entry point for anything that requires the player to exist:

[Subscribe]
private void OnWorldLoaded(WorldLoadedEvent e)
{
    // Safe to call PlayerUtil, SkillUtil, ItemUtil, etc. from here.
    PlayerUtil.HealAll();
}

All PlayerUtil, SkillUtil, and GameUtil methods are null-safe and will return default values (0, false, null) when called outside a loaded world, but they will silently no-op rather than throw. Subscribe to WorldLoadedEvent to ensure your logic runs at the right time.

Clone this wiki locally