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

Using Treesharp switch to choose Combat Routine

spriestdev

New Member
Joined
Sep 19, 2011
Messages
236
Reaction score
11
Hey all,

So I'm having a pretty curious problem here. I'm currently trying to split my CC to support Warlocks as well and running into some odd behavior. It starts and runs fine as a Warlock, however when I try to run it on my Priest I get a "given key is not present in dictionary" error calling a hard stop. I'm assuming this is a look-up against SpellManager.spell["some warlock spell"].

So I've traced this back to the Combat behavior composite here:

Code:
public static LocalPlayer Me { get { return StyxWoW.Me; } }

// The talent spec detection is basically copied and pasted from Singular.
public static Altarboy.TalentSpec ActiveSpec;

        private static Composite CreateCombatBehaviour()
        {
            return new Switch<WoWClass>(ret => Me.Class,
                new ActionAlwaysFail(),
                new SwitchArgument<WoWClass>(WoWClass.Priest,
                    new Switch<TalentSpec>( ret => ActiveSpec,
                        new ActionAlwaysFail(),
                        new SwitchArgument<TalentSpec>(TalentSpec.DisciplinePriest,
                            DisciplinePriest.Combat()
                        ),
                            
                        new SwitchArgument<TalentSpec>(TalentSpec.DisciplineHealingPriest,
                            DisciplinePriest.Combat()
                        ),
                            
                        new SwitchArgument<TalentSpec>(TalentSpec.Lowbie,
                            LowLevelPriest.Combat()
                        ),
                            
                        new SwitchArgument<TalentSpec>(TalentSpec.ShadowPriest,
                            Shadowpriest.Combat()
                        )
                    )),
                new SwitchArgument<WoWClass>(WoWClass.Warlock,
                    new Switch<TalentSpec>(ret => ActiveSpec,
                        new ActionAlwaysFail(),
                        new SwitchArgument<TalentSpec>(TalentSpec.AfflictionWarlock,
                            AfflictionWarlock.Combat()
                        )
                    ))
            );   
        }

Now, I've stared at this code for quite some time and I'm pretty certain that my logic is correct. While debugging this, I've found that if I change AfflictionWarlock.Combat() on the final node there to Shadowpriest.Combat() then everything works and starts normally on my Priest.

I guess I'm just a bit confused on why it's making a call there at all because it should never get anywhere close to that.

Any help or words of wisdom would be greatly appreciated.
 
spriestdev said:
So I'm having a pretty curious problem here. I'm currently trying to split my CC to support Warlocks as well and running into some odd behavior. It starts and runs fine as a Warlock, however when I try to run it on my Priest I get a "given key is not present in dictionary" error calling a hard stop. I'm assuming this is a look-up against SpellManager.spell["some warlock spell"].

I'm assuming your doing something like this:
  • Start Honorbuddy, and play Warlock with your CC for a while
  • /logout of WoWclient, but leave the HB session running
  • Log back in on your Spriest and try to play

If so, when you drop to the toon selection screen, Honorbuddy becomes 'partially unhooked' from the WoWclient. This is bad, even if you log back in on the same toon.

Failure modes for this problem (while questing) include:
  • HB continuously opening and closing a mailbox when it wants to mail
  • HB continuously opening and closing a vendor to sell or repair
  • HB continuously opening and closing a flight master to learn flight paths
  • HB continuously opens and closes an NPC to pick up or turn in a quest
  • HB is confused about 'quest state', or its position in the world
  • HB is confused about spells and skills it should know

In short, any time you drop to the 'toon selection' screen is fail for Honorbuddy. To make it work again correctly, you will need to close that Honorbuddy session (but not the WoWclient) completely and restart it.

In short, all bets are off, and your just bumping into other failure modes (e.g., unable to find spells) for the trigger condition. This is a known limitation of Honorbuddy, and probably will never be corrected.


cheers,
chinajade
 
Last edited:
I sincerely appreciate the time and effort that went into posting that up for me, chinajade.

Unfortunately, I have been launching the bot in the way that you recommended with a complete closure of the application prior to switching toons and then waiting until I am active in the game world (past all loaders) before relaunching Honorbuddy. At one point, I even went to so far as to re-download and extract the current HonorBuddy build to see if the same behavior would carry over. It did.

Even more odd, is that I went with using a Switch after a string of Decorators doing the same thing also produced the exact same unintended result AND that I'm using similar methods to invoke different routines earlier in the same file and that seems to work okay.

If you happen to have a high-level priest (really anything above level 15 *SHOULD* work), you are more than welcome to try this out and see if you get a different result.

https://altarboy.googlecode.com/svn/branches/lock/
 
Last edited:
I see what you're shooting for, however I'm unsure why you don't just use Singular. You seem to be using quite a bit of code from it anyway. (For future reference, just copy the entire talent spec enum, as it'll provide less issues in the long run) I'll be more than happy to provide you SVN access if you wish to go that route. (We all known Singular isn't the greatest with shadow priests at the moment.)

Never, ever, ever, call SpellManager.Spells["Some spell"] without checking if the spell is known (via HasSpell, not SpellManager.Spells.ContainsKey). (Unless of course its a level 1 spell, etc.) You will have exceptions thrown by doing so. I'll modify the indexer for the spell manager so when you try to pull an invalid index, a better error message will be shown.
 
Thank you so much for taking the time to look at this, Apoc. Also, yes, we borrowed some of your code and greatly appreciate you allowing us to use it. It has been an amazing time-saver.

I was able to go through and check that by removing all the SpellManager.Spells["whatever"] calls for the time being until I can go through and do a thorough clean of the code. I still don't understand how it was getting to that code and why it was only affecting one class and not the other, but I've already spent too much time thinking about it.

If I'm understanding you correctly, there was a very generous offer in there to assist with the Shadow Priest portion of Singular. That's very very tempting. However, I'm not entirely sure we could port our target management system into Singular without monkeying around with a bunch of your methods. Additionally, I favor providing the user with a ton of customization options, and I'm not sure you'd want Singular's GUI to have more boxes than a UPS distribution center.
 
Thank you so much for taking the time to look at this, Apoc. Also, yes, we borrowed some of your code and greatly appreciate you allowing us to use it. It has been an amazing time-saver.

I was able to go through and check that by removing all the SpellManager.Spells["whatever"] calls for the time being until I can go through and do a thorough clean of the code. I still don't understand how it was getting to that code and why it was only affecting one class and not the other, but I've already spent too much time thinking about it.

If I'm understanding you correctly, there was a very generous offer in there to assist with the Shadow Priest portion of Singular. That's very very tempting. However, I'm not entirely sure we could port our target management system into Singular without monkeying around with a bunch of your methods. Additionally, I favor providing the user with a ton of customization options, and I'm not sure you'd want Singular's GUI to have more boxes than a UPS distribution center.

Well, Singular's UI is a property grid, which just pulls the properties from the class settings. (Check the "Settings" folder in the singular src) So you can't really clutter the GUI too much, even if you tried. (We allow unlimited settings, descriptions, categories, etc. PropertyGrid makes it easier to deal with dynamically, and the look is consistent across all classes, so there's no confusing differences. Just add your settings to the correct settings class, and its automagically shown on the UI. [Excluding some 'custom' types, which you may need to write custom editors for. But those really shouldn't happen. If they do, just ask and I'll be more than happy to write the editor for it.]) Plus, using a PropertyGrid ensures we're not wasting time making a UI, when its not the UI that matters in a CC. Its the combat. (If people choose a CC solely based on the UI, then something is terribly wrong.)

Depending on what the targeting code does, I doubt there will be an issue. (We have each class separated into their own namespace, so if you need some form of "custom" targeting solution, you're free to do so. Or just create a new "Manager" as we call it, to have your custom targeting support. Just create a new behavior to mimic Safers.EnsureTarget() with your new targeting logic. We try to assume HB's targeting is correct, since we do allow 3rd parties to change things on-the-fly, and people creating their own targeting in a CC, basically removes the entire point of that API.)

Also, Singular is more of a "framework" for CCs. Everything you could possibly need is wrapped (or can be wrapped easily) in a safe way. We do all our class/spec loading dynamically via properties to specify what stuff is for. And we also take into account "global issues" (such as buffing/resting while mounted, dealing with rez sickness, etc) so rotation developers don't need to worry about it. They can just stick to ensuring the rotations work at their best, without having to worry about the tedious details of what CCs need to handle.

If needed, I can help you port whatever you need to Singular, and maybe optimize a few things. (We pride ourselves on being a *very* responsive CC. No fluff, just what needs to be done, and when. Things like pickpocketing, etc, I don't feel should be part of a CC. While its a neat feature to have, stuff like that really isn't worth it in the long run.)
 
Last edited:
Apoc, do you mind PM'ing me so that we can discuss this off thread and work out some details?
 
Back
Top