• Visit Rebornbuddy
  • TreeHooks.Instance.Hooks and TreeHooks.Instance.HookDescriptions

    Discussion in 'Community Developer Forum' started by RahlRB, Aug 31, 2016.

    1. RahlRB

      RahlRB New Member

      Joined:
      Sep 24, 2015
      Messages:
      20
      Likes Received:
      2
      Trophy Points:
      0
      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
       

      Attached Files:

    2. mastahg

      mastahg Administrator Staff Member

      Joined:
      Feb 27, 2011
      Messages:
      5,229
      Likes Received:
      364
      Trophy Points:
      83
      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.
       
    3. RahlRB

      RahlRB New Member

      Joined:
      Sep 24, 2015
      Messages:
      20
      Likes Received:
      2
      Trophy Points:
      0
      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;
      }
      
       
    4. mastahg

      mastahg Administrator Staff Member

      Joined:
      Feb 27, 2011
      Messages:
      5,229
      Likes Received:
      364
      Trophy Points:
      83
      They should not be used. And im not sure what your trying to do there either.
       
    5. RahlRB

      RahlRB New Member

      Joined:
      Sep 24, 2015
      Messages:
      20
      Likes Received:
      2
      Trophy Points:
      0
      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,
       
    6. mastahg

      mastahg Administrator Staff Member

      Joined:
      Feb 27, 2011
      Messages:
      5,229
      Likes Received:
      364
      Trophy Points:
      83
      What you want is HookExecutor

      Code:
       new PrioritySelector(new HookExecutor("PreCombatLogic"));
      
       
    7. RahlRB

      RahlRB New Member

      Joined:
      Sep 24, 2015
      Messages:
      20
      Likes Received:
      2
      Trophy Points:
      0
      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
       
    8. mastahg

      mastahg Administrator Staff Member

      Joined:
      Feb 27, 2011
      Messages:
      5,229
      Likes Received:
      364
      Trophy Points:
      83
      HookExecutor runs whatever hooks are attached to whatever string is passed.
       

    Share This Page