Tech Tree API

Getting started

What you need installed, and the shortest path from an empty project to a node on screen.

Prerequisites

You needWhy
.NET SDK 6.0 or newerThe mod targets net6.0, same as Tech Tree.
BepInEx 6 (IL2CPP build)Supermarket Simulator is an IL2CPP game. The Mono build of BepInEx will not load.
Tech Tree 1.3.0 or newerThe API does not exist in 1.2.0 and below.
A working BepInEx pluginThis page assumes your plugin already loads and logs something.
IL2CPP, not Mono

If your plugin inherits from BaseUnityPlugin you are on the Mono template and it will never load. For IL2CPP the base class is BasePlugin and the entry point is Load(), not Awake().

Four steps

1. Add TechTree.dll to the references you already have

This is one extra reference on top of a normal IL2CPP plugin project, not a replacement for them. You still need BepInEx.Core, BepInEx.Unity.IL2CPP, 0Harmony, Il2CppInterop.Runtime, Il2Cppmscorlib, Assembly-CSharp and whichever UnityEngine.*Module assemblies your code touches. Project setup has the complete, working csproj.

Download the Tech Tree zip from Nexus, take TechTree.dll out of BepInEx/plugins/rodopoulos/, and add it with Private=false:

xml
<!-- IN ADDITION to your usual BepInEx / Harmony / Assembly-CSharp references. -->
<Reference Include="TechTree">
  <HintPath>C:\...\BepInEx\plugins\rodopoulos\TechTree.dll</HintPath>
  <Private>false</Private>
</Reference>

2. Declare the dependency

Without this attribute BepInEx may load your plugin before Tech Tree, and your registration call would hit a type that has not initialised yet.

csharp
[BepInPlugin("BigBoxes", "Big Boxes", "1.0.0")]
[BepInDependency(TechTreeApi.ModGuid)]
public sealed class Plugin : BasePlugin { }

3. Get your module and register

ForPlugin creates your sub-tab inside the Mods tab. The second argument is the label on that sub-tab, and it is the only thing you ever say about where your nodes appear.

csharp
public override void Load()
{
    var tree = TechTreeApi.ForPlugin("BigBoxes", "Big Boxes");

    var handle = tree.Register(new UpgradeDefinition
    {
        Id            = "bigboxes.capacity",
        DisplayName   = "Bigger Boxes",
        MaxLevel      = 3,
        BaseCost      = 1500,
        Icon          = UpgradeIcon.Builtin("package"),
        DescribeLevel = lvl => $"+{lvl * 2} items per box",
    });

    // Register never throws. Check the handle instead.
    if (!handle.Success) Log.LogError(handle.Result.ToString());
}

4. Implement the effect

Tech Tree stores the level. Making it mean something is your job. Read the level with TechTreeApi.GetLevel wherever the game asks the question:

csharp
[HarmonyPatch(typeof(SomeGameClass), "get_BoxCapacity")]
internal static class BoxCapacityPatch
{
    private static void Postfix(ref int __result)
    {
        int lvl = TechTreeApi.GetLevel("bigboxes.capacity");
        if (lvl > 0) __result += lvl * 2;
    }
}

Check it worked

  1. Close the game. BepInEx locks the dll while it runs, so a copy over a running game silently fails.
  2. Copy your dll into BepInEx/plugins/.
  3. Start the game, load a save, sit at the store computer and open Tech Tree.
  4. A Mods tab should be there, with your sub-tab inside it.

If it is not, the log will say why. Open BepInEx/LogOutput.log and search for [api] - every rejection is written there with your plugin guid and the reason.

Nothing showed up at all

An empty sub-tab is never drawn. If every one of your registrations failed, the Mods tab does not appear either - which looks exactly like Tech Tree ignoring you. Check the log before assuming the API is broken.

Common first-run mistakes

SymptomCause
[api] registration of 'X' ... refused - id must be in 'prefix.name' form Ids must contain a dot and be lower case. See Registration.
Two Tech Tree versions load You shipped TechTree.dll with your mod. Set Private=false.
TypeLoadException on your plugin The installed Tech Tree is older than 1.3.0.
Node shows but does nothing You registered it but never wrote the effect. That part is always yours.