UpgradeHandler Basics - PrimeSonic/PrimeSonicSubnauticaMods GitHub Wiki

Originally introduced in the 3.0 update and later refined in the 4.0 overhaul, MoreCyclopsUpgrades can now be used as a public API, allowing other mods to integrate their own cyclops upgrade modules and have them be fully compatible with the Auxiliary Upgrade Console.


Introducing the UpgradeHandler class

The UpgradeHandler is a class that MoreCyclopsUpgrades uses to take action whenever a matching upgrade module is found.
Cyclops upgrade modules, like every other item in the Subnautica code base, is identified by its TechType value.

Whenever MoreCyclopsUpgrades is checking the TechType values of all upgrade modules equipped in the Cyclops,
it will look for an UpgradeHandler that manages that TechType.

Over the course of the Cyclops upgrade cycle, MoreCyclopsUpgrades will call each UpgradeHandler to act.

What you need to provide

There are several public event fields where you can register what actions to take during upgrade handling.
These here are the most basic ones you will want to be aware of as they correspond to the upgrade cycle explained above.

  1. OnClearUpgrades
  • This event is invoked when upgrades are cleared right before being re-counted.
  • This happens every time upgrades are changed and only once per each type of upgrade.
  • The Count property is reset to 0 after this event is complete.
  1. OnUpgradeCounted and OnUpgradeCountedDetailed
  • These events are invoked when a matching upgrade module is found and counted.
  • This will happen for each copy found in the cyclops upgrade consoles.
  • The Count property is increased before this event starts.
  • The "Detailed" variation is here in case you need a reference to the actual InventoryItem and where it is located.
  1. OnFinishedUpgrades
  • This event is invoked after all upgrade modules have been found and counted.
  • This event is always invoked, no matter how many copies were found or not.
    • This is so if your upgrade handler needs to account for the case where the upgrade isn't present, such as with depth modules and tiered engine efficiency upgrades, that can be here if you choose.
    • It is up to you to check the Count or HasUpgrade properties and respond accordingly.

Examples of a Simple UpgradeHandler

// Make sure you include this in your using statements to gain access to the UpgradeHandler class
using MoreCyclopsUpgrades.API.Upgrades;

Using the above events, here's two different ways you could create an UpgradeHandler for a simple upgrade that is either on or off.

Using the OnClearUpgrades and OnUpgradeCounted events.

return new UpgradeHandler(TechType.CyclopsShieldModule, cyclops)
{
    OnClearUpgrades = () => { cyclops.shieldUpgrade = false; },
    OnUpgradeCounted = () => { cyclops.shieldUpgrade = true; }
};

Using just the OnFinishedUpgrades event.

var csm = new UpgradeHandler(TechType.CyclopsShieldModule, cyclops);
csm.OnFinishedUpgrades = () =>
{
    cyclops.shieldUpgrade = csm.HasUpgrade;
};
return csm;

Making your own UpgradeHandler class

internal class CyclopsShieldUpgradeHandler : UpgradeHandler
{
    internal CyclopsShieldUpgradeHandler(SubRoot cyclops) : base(TechType.CyclopsShieldModule, cyclops)
    {
        base.OnFinishedUpgrades = HandleShield;
    }
    
    private void HandleShield()
    {
        base.Cyclops.shieldUpgrade = base.HasUpgrade;
    }
}

You can find more simple examples here, where all of the vanilla cyclops upgrade were re-created for MoreCyclopsUpgrades.


If your upgrade module can't be self-contained and instead you need an external component to check if it is installed, you have a few options:

  1. For simple upgrades, you can pass your TechType value to the HasUpgradeInstalled method of the MCU CrossMod Service
  2. Find your upgrade handler and check the value of its HasUpgrade or Count properties.

Accessible Members on UpgradeHandler

This is the full list of public members on the UpgradeHandler class, accessible to any external mod.

Member Access Type Notes
Cyclops readonly SubRoot Reference to the cyclops sub this handler is upgrading
TechType readonly TechType The TechType that this handler is listening for
Count get-only int The number of copies of this upgrade currently in the cyclops
MaxCount get/set int The maximum number of copies of this upgrade the cyclops sub can support
MaxLimitReached get-only bool Returns true when the max number of copies are installed
HasUpgrade get-only bool Returns true when there is at least one copy of this upgrade installed
OnClearUpgrades event UpgradeEvent Event invoked upgrades are first cleared for re-counting
OnUpgradeCounted event UpgradeEvent Event invoked when a copy of this upgrade is found
OnUpgradeCountedDetailed event UpgradeEventSlotBound Event invoked when a copy of this upgrade is found, includes slot data
OnFinishedUpgrades event UpgradeEvent Event invoked after all upgrades have been counted
OnFirstTimeMaxCountReached event Action Event invoked the first time the max number of copies is reached
IsAllowedToAdd event UpgradeAllowedEvent Event invoked when attempting to add this upgrade
IsAllowedToRemove event UpgradeAllowedEvent Event invoked when attempting to remove this upgrade
TrackedItems get-only IEnumerable<InventoryItem> readonly collection of all the specific upgrade modules as Inventory Items
SourceMod get-only string Name of the mod that registered this UpgradeHandler