Перейти к основному содержимому
The project's repository is archived as part of the GitHub Archive Program. RogueLibs' code and the documentation will no longer be updated.

Хуки

Интерфейс IHook

Итак, хук - это объект, прицепляемый к другому объекту. В RogueLibs типы хуков наследуют от IHook и IHook<T>.

RogueLibsPatcher.dll создаёт поля под названиями __RogueLibsHooks во всех типах, на которые можно прицепить хуки. Объект класса IHookController потом назначается в это поле для управления прицепленными хуками. Он предоставляет методы для получения, прицепления и отцепления хуков от текущего объекта. Думайте о нём как о коллекции хуков.

Вы можете создавать свои хуки наследуя от IHook<T> или от HookBase<T>:

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

public void StoreInfo(string data)
{
Debug.Log($"Сохранено {data}.");
Data = data;
}
public string LoadInfo()
{
Debug.Log($"Загружено {Data}.");
return Data;
}
private string Data;
}

Использование

Вы можете использовать хуки для хранения всякой информации:

MyCustomHook hook = item.AddHook<MyCustomHook>();
hook.StoreInfo("какая-то-информация");

Потом вы можете использовать эту информацию где-нибудь в другом месте:

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

Вы можете прицеплять несколько хуков одного типа тоже:

MyCustomHook hook = item.AddHook<MyCustomHook>();
hook.StoreInfo("какая-то-информация");
MyCustomHook hook = item.AddHook<MyCustomHook>();
hook.StoreInfo("что-то-другое");
MyCustomHook hook = item.AddHook<MyCustomHook>();
hook.StoreInfo("что-нибудь-ещё");
foreach (MyCustomHook hook in item.GetHooks<MyCustomHook>())
{
string data = hook.LoadInfo();
}
Совет от профи: Фабрики хуков

Если вы хотите прицеплять хуки к объектам прямо когда они инициализируются, используйте Фабрики хуков.

Примеры

Кстати, кастомные классы (CustomItem, CustomTrait, CustomEffect, CustomAbility и другие) тоже хуки:

к сведению

Смотрите реализацию кастомных классов в исходном коде RogueLibs.

Отличный пример с кастомными хуками, отслеживающими приправленные предметы.

Смотрите пример объединяемого предмета тут.

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.