Mastahg, I am currently getting some very interesting behavior out of the following 2 API calls: TreeHooks.Instance.Hooks TreeHooks.Instance.HookDescriptions I am currently using the following code to test these in the RebornConsole: Code: Log(BotManager.Current.EnglishName); Log("\n"); foreach (var hook in ff14bot.Behavior.TreeHooks.Instance.Hooks) { Log(hook.Key); } Log("\n"); foreach (var hookDescription in ff14bot.Behavior.TreeHooks.Instance.HookDescriptions) { Log(hookDescription.Name + ":\t" + hookDescription.Description); } Currently, when I just start a brand new instance of RB and I haven't actually started any BotBase, when I run the above code this is what I'm getting: Code: Combat Assist TreeStart PoiAction PreCombatBuff Heal Pull CombatBuff Combat Rest Notice how I'm getting the name of the Hooks, but I'm not getting any HookDescriptions at all. Now is where things are really getting weird for me and I don't understand what is causing them to happen. As soon as I hit Start on RB to start running the BotBase, I now get this result from running the same code snippet in the Console: Code: Combat Assist TreeStart PoiAction PreCombatBuff Heal Pull CombatBuff Combat Rest DeathReturnLogic DeathReturnLogic: This logic runs if the player has died and succesfully revied Notice how we have a new Hook showing up (DeathReturnLogic) and we are finally getting a HookDescription as well (for DeathReturnLogic). Why this is weird to me is because I've looked at the code in RaidBro.cs (Combat Assist) and I don't see it adding a new HookExecutor or a new HookDescription anywhere. Further confusion is caused when I click the Stop button in RB. After clicking Stop and re-running the same code snippet, I get the following results: Code: Combat Assist TreeStart PoiAction PreCombatBuff Heal Pull CombatBuff Combat Rest DeathReturnLogic DeathReturnLogic: This logic runs if the player has died and succesfully revied DeathReturnLogic: This logic runs if the player has died and succesfully revied It looks like there is something wrong within the BotStop methods somewhere. The reason I say this, is because if I click Start and then run the code snippet again, I get the same results...but as soon as I hit Stop and then run the code snippet again, I get another duplicate entry in the HookDescriptions. Here's a result after Starting/Stopping the bot many times: Code: Combat Assist TreeStart PoiAction PreCombatBuff Heal Pull CombatBuff Combat Rest DeathReturnLogic DeathReturnLogic: This logic runs if the player has died and succesfully revied DeathReturnLogic: This logic runs if the player has died and succesfully revied DeathReturnLogic: This logic runs if the player has died and succesfully revied DeathReturnLogic: This logic runs if the player has died and succesfully revied DeathReturnLogic: This logic runs if the player has died and succesfully revied DeathReturnLogic: This logic runs if the player has died and succesfully revied DeathReturnLogic: This logic runs if the player has died and succesfully revied Can you give any insight on why the API is inserting a new hook (DeathReturnLogic). Can you also look into the duplicate entries into the HookDescriptions. Thanks, Rahl
PreCombatBuff Heal Pull CombatBuff Combat Rest are internal hooks used to support the swapping of combat routines and as such do not have descriptions. deathreturnlogic is the hook that is used to handle getting back to where you are when you die. We don't check if its already added and since it doesn't effect anything im going to leave it.
Thank you for the clarification. Since the above mentioned hooks are internal, should we not use those hooks in custom botbases? IE: Is something like this bad practice? Code: if (RoutineManager.Current.CombatBehavior != null) { foreach (var action in TreeHooks.Instance.Hooks["Combat"]) { try { if (await action.ExecuteCoroutine()) return true; } catch (Exception ex) { Logging.WriteException(Colors.Red, ex); } await Coroutine.Yield(); } if (await RoutineManager.Current.CombatBehavior.ExecuteCoroutine()) return true; }
In essence, what I'm trying to do is figure out how to execute the hooks that Plugins are attaching to in a custom botbase. I've taken a look at the botbases that come with RB and didn't see an example of how to do that. I added in using the internal hooks because I was going off of memory that you advised Neverdyne to hook into a PreCombat hook for his Zekken Plugin (Zekkenl). I've just looked at the source for that Zekken Plugin and realized that he is hooking to "PreCombatLogic" which I'm assuming is a custom HookExecutor that you've created. I know that most plugins are just hooking themselves to the TreeStart Hook, so I came up with the following code to actually execute those plugins: Code: public static class Hooks { static Hooks() { Composite = new ActionRunCoroutine(ctx => Run()); } public static Composite Execute() { return Composite; } private static readonly Composite Composite; private static async Task<bool> Run() { foreach (var action in TreeHooks.Instance.Hooks["TreeStart"]) { try { if (await action.ExecuteCoroutine()) return true; } catch (Exception ex) { Logging.WriteException(Colors.Red, ex); } await Coroutine.Yield(); } return false; } } And that code gets used in the Root Composite of the BotBase...which looks like this: Code: Root = new Decorator(r => Core.Me.IsAlive, new PrioritySelector( Tank.Execute(), Healer.Execute(), Damage.Execute(), Helpers.Execute(), Hooks.Execute())); I've tested that the above code does actually work by using a simple eat food if I don't have the food buff plugin. If you would be willing to share some sample code for best practices around executing all of the composites that have been hooked into one of the TreeHooks, that would be great! Thanks,
Well don't I feel silly...thanks! That makes things a lot simpler! Based off the Summary on the class itself: I thought HookExecutor was only used to define your own custom hook locations to allow others to attach to. Code: Root = new Decorator(r => Core.Me.IsAlive, new PrioritySelector( Tank.Execute(), Healer.Execute(), Damage.Execute(), Helpers.Execute(), new HookExecutor("TreeStart"))); ^^ Much simpler now! Thanks again for the clarification. -Rahl