What's new
  • Visit Rebornbuddy
  • Visit Panda Profiles
  • Visit LLamamMagic
  • Visit Resources
  • Visit Downloads
  • Visit Portal

TreeSharp.Decorator info (creating a Decorator class)

jim87

New Member
Joined
Aug 26, 2011
Messages
445
Reaction score
7
Hello!

I'm just unsure about the overrides I have to write to make it work as intended. I usually created Decorators within the treesharp behaviors directly (like new Decorator(CanRunDecoratorDelegate func, Composite decorated)), but from a logic-flow point-of-view, it's way better to create meaningfull-named decorators and place them in the behavior root once implemented (IMHO).

I thus created a new Decorator class, and I think I understood some of the overrides, may you explain me the others / correct me if wrong? Thanks :):

PHP:
using TreeSharp;

namespace MyProject.Decorators
{
    class DecoratorMyDecorator : Decorator
    {
        protected override bool CanRun(object context)
        {
            // used as CanRunDecoratorDelegate func
        }

        protected override IEnumerable<RunStatus> Execute(object context)
        {
            // used as Composite decorated? May I return an Action? Should be fine as
            // actions return a RunStatus
        }

        public override void Start(object context)
        {
            // used when? (Start/Stop)
        }

        public override RunStatus Tick(object context)
        {
            // used when?
        }
    }
}
 
Hello!

I'm just unsure about the overrides I have to write to make it work as intended. I usually created Decorators within the treesharp behaviors directly (like new Decorator(CanRunDecoratorDelegate func, Composite decorated)), but from a logic-flow point-of-view, it's way better to create meaningfull-named decorators and place them in the behavior root once implemented (IMHO).

I thus created a new Decorator class, and I think I understood some of the overrides, may you explain me the others / correct me if wrong? Thanks :):

When trying to write a Decorator sub-class as you are...
just override the CanRun() method, and allow the parent class (Decorator) to handle everything else. I.e., don't override any other methods. Its simple this way, and it works well.


cheers,
chinajade
 
Yeah, but what about the action, if I want to include one in it directly? Thanks :-)
 
Yeah, but what about the action, if I want to include one in it directly? Thanks :-)

For a custom Action, you should create a derived Action also.

Its not the Decorator's job to perform actions--just 'contain' them. In your derived Decorator, just let the parent 'hold' the appropriate derived Action.


cheers,
chinajade
 
The good thing about object-oriented programming is that you don't have to know what's behind the object - you just use it and its methods and in case override them (or overload)... I'm gonna read the sources...
 
What you're doing is creating a behavior, not a decorator.

You'll want to create a method to return the common behavior, not a decorator and hack in an action on top of it. (Thats not how it works, nor how it was coded)

Deriving from Decorator means you're going to provide some form of common conditional. Not a condition followed by an action.
 
I was unsure whenever to post here or on a new thread... anyway... I'm encourring in an "System.NullReferenceException: Object reference not set to an instance of an object" error...
PHP:
        protected override bool CanRun(object context)
        {
            // Random _r = new Random();
            // We've cast fishing less than 1.0 - 1.5 - 2.0 seconds ago, we can't cast fishing too early
            // (avoid bot-like reaction)
#warning TODO: return if previous comment (need singleton)
            LocalPlayer Me = ObjectManager.Me;
            WoWObject nearestPool = Utils.getNearestPool();
            WoWGameObject bobber = Utils.getBobber();
            List<WoWGameObject> otherBobbers = Utils.getOtherBobbers();
            bool othersFishingSamePool = false;
            
#warning TODO: override if setting steal pools is on
            if (otherBobbers.Count > 0)
            {
                foreach (WoWGameObject go in otherBobbers)
                {
                    if (go.GetPosition().Distance2D(nearestPool.GetPosition()) <= 10.0f)
                    {
                        othersFishingSamePool = true;
                        break;
                    }
                }
            }

            if (!(LootFrame.Instance != null && LootFrame.Instance.IsVisible) && // we're not looting anything <-- error! Object reference not set to an instance of an object.
                nearestPool != null && // the pool actually exists
                !othersFishingSamePool && // we don't want to let anyone get angry
                !Me.Mounted && // can't cast while mounted
                !Me.IsSwimming && // can't cast while swimming
                nearestPool.Distance2D <= 20.0 && // I'm within 20 yards
                WoWMathHelper.IsFacing(Me.Location, Me.Rotation, nearestPool.Location, 2.0f) && // I'm facing the pool
                bobber == null || bobber.GetPosition().Distance2D(nearestPool.GetPosition()) >= 3.4f // No bobber, or bobber distance > 3.4f from pool
                    )
            {
                // Start the fishing stopwatch
                FishingCastInterval.Reset();
                FishingCastInterval.Start();
                return true;
            }
            return false;
        }

Is there something I'm doing wrong? I first check whenever the LootFrame (using Styx.Logic.Inventory.Frames.LootFrame) is not null and then (if not) if it's opened. The same error is fired even if I use the simple bool ObjectManager.Me.Combat, isn't Me allways defined within the bot? What's the way I should code this part?
 
Last edited:
I was unsure whenever to post here or on a new thread... anyway... I'm encourring in an "System.NullReferenceException: Object reference not set to an instance of an object" error...
PHP:
        protected override bool CanRun(object context)
        {
            // Random _r = new Random();
            // We've cast fishing less than 1.0 - 1.5 - 2.0 seconds ago, we can't cast fishing too early
            // (avoid bot-like reaction)
#warning TODO: return if previous comment (need singleton)
            LocalPlayer Me = ObjectManager.Me;
            WoWObject nearestPool = Utils.getNearestPool();
            WoWGameObject bobber = Utils.getBobber();
            List<WoWGameObject> otherBobbers = Utils.getOtherBobbers();
            bool othersFishingSamePool = false;
            
#warning TODO: override if setting steal pools is on
            if (otherBobbers.Count > 0)
            {
                foreach (WoWGameObject go in otherBobbers)
                {
                    if (go.GetPosition().Distance2D(nearestPool.GetPosition()) <= 10.0f)
                    {
                        othersFishingSamePool = true;
                        break;
                    }
                }
            }

            if (!(LootFrame.Instance != null && LootFrame.Instance.IsVisible) && // we're not looting anything <-- error! Object reference not set to an instance of an object.
                nearestPool != null && // the pool actually exists
                !othersFishingSamePool && // we don't want to let anyone get angry
                !Me.Mounted && // can't cast while mounted
                !Me.IsSwimming && // can't cast while swimming
                nearestPool.Distance2D <= 20.0 && // I'm within 20 yards
                WoWMathHelper.IsFacing(Me.Location, Me.Rotation, nearestPool.Location, 2.0f) && // I'm facing the pool
                bobber == null || bobber.GetPosition().Distance2D(nearestPool.GetPosition()) >= 3.4f // No bobber, or bobber distance > 3.4f from pool
                    )
            {
                // Start the fishing stopwatch
                FishingCastInterval.Reset();
                FishingCastInterval.Start();
                return true;
            }
            return false;
        }

Is there something I'm doing wrong? I first check whenever the LootFrame (using Styx.Logic.Inventory.Frames.LootFrame) is not null and then (if not) if it's opened. The same error is fired even if I use the simple bool ObjectManager.Me.Combat, isn't Me allways defined within the bot? What's the way I should code this part?

Did you try Hooking to HB and stepping it line by line?
 
Well, the error is actually on the first line of the if conditional, what should I search within the debugger exactly?
 
I see 3 things that can be null in that code. If you're not going to put in the time to debug it, I'm not going to be of any help to you anyway.

Attach VS to HB while it's running. Put a breakpoint there. If you don't how how to do simple debugging, then you should probably go learn.
 
Meh, I rewrote the conditional and now it works flawlessy. BTW just for interest, I tried to comment one by one all the conditions, the error was always on the first line of the if statement.

BTW if you're referring to the Utils methods, getNearestPool() and getBobber() return an object or null, and they're both first checked before interacting with, while getOtherBobbers() always return a List.

This is the functioning code
PHP:
            if (!Me.Mounted && // I'm not mounted
                !Me.IsSwimming && // I'm not swimming
                !Me.IsMoving && // I'm not moving
                !Me.Combat && // I'm not in combat
                !looting && // I'm not looting
                nearestPool != null &&// The pool exists
                !othersFishingSamePool && // we don't want to let anyone get angry
                nearestPool.Distance2D <= 20.0 && // I'm within 20 yards
                (bobber == null || (bobber != null && bobber.GetPosition().Distance2D(nearestPool.GetPosition()) >= 3.4f)) && // No bobber, or bobber distance > 3.4f from pool
                WoWMathHelper.IsFacing(Me.Location, Me.Rotation, nearestPool.Location, 0.80f) // I'm facing the pool (30? grad tollerance)
                ) return true;

looting is the same bool returned by the one used in the previous code. Is it possible that the runtime-compiler just used a cached compiled object? Or it doesn't save the objects before linking?
 
Back
Top