That feature allows you to Link from BT/Macro another aura containing C# Script
action - this is equivalent of you "referencing" another project in programming.
All the classes and types defined in that script will become available to you for use in BTs.
Referencing has existed for many months by now, but was "hidden" from a public eye as it was not fully complete and was not working in a way I wanted it to.
Now you can have C# class, which will analyze the game - be it via Computer Vision triggers or by directly reading values from memory - and provide BehaviorTree with a data necessary for making a decision.
Instead of cluttering the tree with all the checks and having 50 different Variables, you can now have a single class, e.g. TheGame
, which will be wrapping up ways of getting the info.
This is a bot which under the hood uses that same approach which I will be outlining below.
First, lets take a look at "Shared" aura and files which it has.
public sealed class TheGame {
public TheGame(IFluentLog log){
Log = log;
}
public IFluentLog Log {get;}
public int IntValue { get; private set; }
public void Refresh()
{
IntValue++; //in real-world apps, this could be the code reading values from Memory or calling Refresh on Triggers
Log.Info($"Refreshed the state, value: {IntValue}");
}
}
In that class we have all the scaffolding done and prepared - we initialize triggers OR prepare everything for memory-reading, maybe create some OSD - basically prepare to do the actual work.
Whenever Refresh
method gets called, the actual data refresh happens. In the example which I am showing, this is happening as a part of a ticking BT. In real-world scenarios this could be on timer, from BT, manually OR even all the methods combined - you're not restricted by anything here, do whatever you want.
[Inject] IAuraTreeScriptingApi AuraTree {get; init;}
Log.Info("Bot is being started!");
var tree = AuraTree.GetBehaviorTreeByPath("./New tree");
var game = GetService<TheGame>(); //create TheGame
tree["TheGame"] = game; //save instance to Variables, making it possible to access it from BTs/Macros
This is how we're propagating TheGame to BT - via Variables. This is the key part that was missing before. From now on, objects passed via Variables should be fully accessible and there are no restrictions on values that are being passed around.
Now getting to BT. Here is an example structure which you could use.
var game = Variables.Get<CheatCrescendo.TheGame>("TheGame").Value;
game.Refresh();
In the first node, we call Refresh
, which is expected to refresh game state, actualize it and make it possible to consume in further nodes.
Keep in mind, that variable "TheGame" by that point is already filled and points to an instance of TheGame we've created before. Surely you can just have another node in the tree creating that on the first run, but that is up to you to decide. Somehow, you have to create "TheGame" before accessing it here.
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;
}
}
That is an example of EyeAuras-driven OnScreenDisplay, which can draw whatever you want on the screen. You do not really need it, it is just an example of what you could have. It uses recently-added IEnumerator<NodeStatus>
approach, which allows you to "split" node lifecycle in parts.
In that case, we're creating OSD on the first run of the node and then simply update it on all consequent runs. As this always happens right after Refresh
has been called, your OSD will be tightly in sync with that bot "sees".
That is an example of how you can utilize OSD to better "visualize" decision-making of the bot. Note those colored lines and figures - all of them mean something and having that drawn on the screen immensely happens with debugging. Also it looks cool.
And under that selector you can have however many nodes, checking the actual state of the game. Considering all those nodes have access to TheGame
object and its methods, you can do whatever you want here. Expose HP as a number that is read directly from memory ? No problem, write that logic in TheGame, call that method from BT Node and you're good to go. Or you can have that same method reading the value from ColorSearch trigger doing color analysis check. Or you can use TextSearch to get that value from UI.
What is also cool is the fact that you can have methods doing something, i.e. you expose a method which uses a bunch of operations to get you from Town A to town B - opens portal, selects and option, clicks on it, etc. Then you simply call that method from BT and it takes you wherever you wanted.
A whole bunch of performance-related changes. Please report any problems you will notice.
PoeShared.Blazor.Controls
that contains default EyeAuras controls is now exposed to scripts by default