Skip to content

Getting Started

QinShenYu edited this page Jun 16, 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>

Recommended target framework (0.7.2+)

ScavLib 0.7.2 itself targets ​.NET Framework 4.8 and is built with <LangVersion>latest</LangVersion>. The produced DLL is IL-compatible with mods still targeting 4.7.2, but matching the host framework is recommended so you can use the same modern C# syntax in your own code:

<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<LangVersion>latest</LangVersion>

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, CustomItemTag, VanillaLimb, VanillaWearSlot
ScavLib.command BaseCommand, CommandRegistry
ScavLib.config ConfigManager
ScavLib.gui.ugui UguiWindowBase, UguiBuilder, UguiTheme, UguiPixelBar, UguiNumberField, UguiDropdown, UguiToggleGroup, UguiTabView, UguiHorizontalRow
ScavLib.gui.imgui ImguiWindow, ImguiMenuBuilder, ImguiMenuManager
ScavLib.mods ModInfo, ModRegistry, IModLifecycle, ModLifecycleBase, ModSession, VersionedDependency
ScavLib.recipe RecipeBuilder, CustomRecipeRegistry
ScavLib.liquid CustomLiquidBuilder, CustomLiquidRegistry
ScavLib.i18n (0.7.2) LocaleManager, TranslationTemplateGenerator, LocalePatches
ScavLib.save (0.7.2) ICustomItemSaveable, SaveCompanionFile, MissingItemTag, SaveDataSchema
ScavLib.compat (0.7.2) RivalFrameworkDetector
ScavLib.compat.krokmp (0.7.2) KrokMpBridge

Removed in 0.7.2:​ the old ScavLib.locale namespace and LocaleRegistry class. The replacement under ScavLib.i18n is described on the i18n page; see the Changelog for the migration path.


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.


Multiplayer (Krokosha MP)

If KrokoshaCasualtiesMP is installed, ScavLib activates a built-in bridge that makes custom items sync correctly across clients, fixes Con.SpawnThingOnPlayer for dedicated servers, and keeps companion save files inside the active MP save directory. You do not need to opt in — the bridge is a soft dependency and turns itself on automatically when KrokMP is present.

There is nothing special to do in your mod code: anything you register through CustomItemBuilder is MP-aware out of the box. See the Multiplayer Compatibility page for known limitations (notably: OnSpawn runs on every client independently; CustomItemTag.InstanceData is not auto-synced — use GOSyncPacket for state that must be authoritative).

Clone this wiki locally