Skip to main content
The project's repository is archived as part of the GitHub Archive Program. RogueLibs' code and the documentation will no longer be updated.

Hooks

A hook is an object that is attached to another object ("hook" is a really vague word, jsyk). In RogueLibs hook types derive from IHook and IHook<T>, and RogueLibs provides a mechanism to attach these hooks to vanilla types, such as InvItem, PlayfieldObject, Unlock, Trait and etc. Most custom content classes are based on hooks in one way or another.

IHook interface

RogueLibsPatcher.dll creates fields called __RogueLibsHooks in all hookable types. An instance of IHookController class is then assigned to the __RogueLibsHooks field to manage the attached hooks. It provides methods to get, attach and detach hooks from the current instance. Think of it as a collection of hooks.

You can create your own hooks by deriving either from IHook<T> or from HookBase<T>:

MyCustomHook.cs
public class MyCustomHook : HookBase<InvItem>
{
protected override void Initialize() { }

public void StoreInfo(string data)
{
Debug.Log($"Stored {data}.");
Data = data;
}
public string LoadInfo()
{
Debug.Log($"Loaded {Data}.");
return Data;
}
private string Data;
}

Usage

You can use hooks to store various stuff:

MyCustomHook hook = item.AddHook<MyCustomHook>();
hook.StoreInfo("some-information");

Then you can use that stuff somewhere else:

MyCustomHook hook = item.GetHook<MyCustomHook>();
if (hook != null)
{
string data = hook.LoadInfo();
}

You can attach more than one hook of a type too:

MyCustomHook hook = item.AddHook<MyCustomHook>();
hook.StoreInfo("some-information");
hook = item.AddHook<MyCustomHook>();
hook.StoreInfo("some-other-stuff");
hook = item.AddHook<MyCustomHook>();
hook.StoreInfo("something-else");
foreach (MyCustomHook hook in item.GetHooks<MyCustomHook>())
{
string data = hook.LoadInfo();
}
Pro-tip: Hook Factories

If you want to attach hooks to instances right when they are initialized, use Hook Factories.

Examples

info

Custom content classes (CustomItem, CustomTrait, CustomEffect, CustomAbility and others) are hooks, by the way. You can see the custom classes' implementation in RogueLibs' source code.

A great example with custom hooks keeping track of seasoned items.

See the combinable item example here.

using UnityEngine;

namespace RogueLibsCore.Test
{
[ItemCategories(RogueCategories.Food, RogueCategories.Health)]
public class SpiceRack : CustomItem, IItemCombinable
{
[RLSetup]
public static void Setup()
{
RogueLibs.CreateCustomItem<SpiceRack>()
.WithName(new CustomNameInfo("Spice Rack"))
.WithDescription(new CustomNameInfo("Combine with any food item to increase its healing properties."))
.WithSprite(Properties.Resources.SpiceRack)
.WithUnlock(new ItemUnlock
{
UnlockCost = 10,
LoadoutCost = 3,
CharacterCreationCost = 2,
Prerequisites = { VanillaItems.FoodProcessor },
});

SeasonCursorText = RogueLibs.CreateCustomName("SeasonItem", NameTypes.Interface, new CustomNameInfo("Season"));
}
private static CustomName SeasonCursorText = null!;

public override void SetupDetails()
{
Item.itemType = ItemTypes.Combine;
Item.itemValue = 4;
Item.initCount = 10;
Item.rewardCount = 15;
Item.stackable = true;
Item.hasCharges = true;
}
public bool CombineFilter(InvItem other)
{
if (other.itemType != ItemTypes.Food || other.healthChange is 0
|| !other.Categories.Contains(RogueCategories.Food)) return false;

SpicedHook? hook = other.GetHook<SpicedHook>();
return hook is null || hook.Spiciness < 3;
}
public bool CombineItems(InvItem other)
{
if (!CombineFilter(other)) return false;

SpicedHook hook = other.GetHook<SpicedHook>() ?? other.AddHook<SpicedHook>();
hook.IncreaseSpiciness();

Count--;
gc.audioHandler.Play(Owner, VanillaAudio.CombineItem);
return true;
}
public CustomTooltip CombineCursorText(InvItem other) => SeasonCursorText;
public CustomTooltip CombineTooltip(InvItem other)
{
if (!CombineFilter(other)) return default;

SpicedHook? hook = other.GetHook<SpicedHook>();
int bonus = hook is null ? (int)Mathf.Ceil(other.healthChange / 4f) : hook.HealthBonus;
return new CustomTooltip($"+{bonus}", Color.green);
}

private class SpicedHook : HookBase<InvItem>
{
protected override void Initialize()
=> HealthBonus = (int)Mathf.Ceil(Instance.healthChange / 4f);

public int HealthBonus { get; private set; }
public int Spiciness { get; private set; }

public void IncreaseSpiciness()
{
if (Spiciness is 3) return;

Spiciness++;
Instance.healthChange += HealthBonus;
}
}
}
}

The project's repository is archived as part of the GitHub Archive Program. RogueLibs' code and the documentation will no longer be updated.