1.7.8378
C#-скрипты — Advanced — Ссылки на скрипты из BT/Макросов
Эта функция позволяет вам привязать из BT/макроса другую ауру, содержащую действие C# Script — это эквивалентно тому, как если бы вы «ссылались» на другой проект в программировании.
Все классы и типы, определённые в этом скрипте, станут доступны для использования в BT.
Механизм ссылок существует уже несколько месяцев, но ранее он был «спрятан» от глаз, так как был неполноценным и не работал так, как мне хотелось.

Зачем это нужно?
Теперь вы можете создать класс C#, который будет анализировать игру — через триггеры компьютерного зрения или напрямую читая память — и предоставлять BehaviorTree необходимые данные для принятия решений.
Вместо того чтобы загромождать дерево десятками переменных и проверок, вы просто создаёте один класс, например TheGame, который инкапсулирует всё получение информации.
Пример бота
Этот бот использует именно тот подход, который описан ниже. Он знает окружение, статы свои и окружающих монстров, может строить план действий и т.п. В целом в таком подходе ограничение я пока встретил только одно - свой собственный потолок.

Аура со скриптом внутри
Посмотрим на "Shared"-ауру и её файлы.
TheGame.cs
public sealed class TheGame {
public TheGame(IFluentLog log){
Log = log;
}
public IFluentLog Log {get;}
public int IntValue { get; private set; }
public void Refresh()
{
IntValue++; // в реальности здесь может быть чтение из памяти или обновление триггеров
Log.Info($"Refreshed the state, value: {IntValue}");
}
}
Класс готовит всё для логики: инициализация триггеров, чтение из памяти, создание OSD — всё, что нужно.
Когда вызывается Refresh, происходит обновление состояния.
Script.csx
[Inject] IAuraTreeScriptingApi AuraTree {get; init;}
Log.Info("Bot is being started!");
var tree = AuraTree.GetBehaviorTreeByPath("./New tree");
var game = GetService<TheGame>();
tree["TheGame"] = game;
Так мы передаём объект TheGame в BT через переменные.
Это ключевая часть, которая раньше отсутствовала. Теперь передаваемые через переменные объекты доступны полностью и без ограничений.
Behavior Tree
Пример структуры дерева:

Обновление данных
var game = Variables.Get<CheatCrescendo.TheGame>("TheGame").Value;
game.Refresh();
В этом узле вызываем Refresh, который обновляет состояние игры. Переменная "TheGame" к этому моменту уже инициализирована — либо скриптом, либо другой нодой.
Отрисовка OSD
return Run();
public IEnumerator<NodeStatus> Run(){
using var osd = GetService<IOnScreenCanvasScriptingApi>().Create();
var game = Variables.Get<CheatCrescendo.TheGame>("TheGame").Value;
var textOsd = osd.AddHtmlObject();
while (!cancellationToken.IsCancellationRequested){
textOsd.Html = $"{game.IntValue}";
yield return NodeStatus.Success;
}
}
Это пример создания OSD, который визуализирует текущее значение IntValue.
Используется новая возможность — IEnumerator<NodeStatus>, позволяющая "разбивать" жизненный цикл ноды.
В первом запуске создаётся OSD, далее оно просто обновляется.
Логика игры
Под селектором можно размещать сколько угодно нод, проверяющих текущее состояние.
Всё, что нужно — обращаться к TheGame и вызывать его методы.
Например, хотите получить HP напрямую из памяти? Напишите метод в TheGame — вызывайте его из BT-ноды.
Нужна проверка по цвету через ColorSearch? То же самое.
Даже движение между локациями можно вынести в метод: открыть портал, выбрать опцию, кликнуть — всё в TheGame, один вызов из BT.
Производительность
Добавлено множество улучшений, влияющих на производительность. Если заметите проблемы — сообщайте.
Исправления / Улучшения
- [Behavior Trees] Прототип параллельной загрузки узлов — должно ускорить загрузку больших деревьев
- [Scripting] Пространство имён
PoeShared.Blazor.Controls, содержащее элементы управления, теперь доступно из скриптов по умолчанию