Hey there, while coding my CC, I just came across the following problem: How can I switch between 3 internal behaviours, depending on the add count? As an intro, here are the relevant code snippets: Code: private List<WoWUnit> adds = new List<WoWUnit>(); private List<WoWUnit> detectAdds() { List<WoWUnit> addList = ObjectManager.GetObjectsOfType<WoWUnit>(false).FindAll(unit => unit.Guid != Me.Guid && unit.Distance < 10.00 && (unit.IsTargetingMyPartyMember || unit.IsTargetingMyRaidMember || unit.IsTargetingMeOrPet) && !unit.IsFriendly && !unit.IsPet && !Styx.Logic.Blacklist.Contains(unit.Guid)); return addList; } From which I am able to retrieve the number of adds by calling Code: adds.Count When the CombatBehaviour looks like this: Code: protected Composite CreateBossBehavior() { adds = detectAdds(); return new Switch(bool) (ret => adds.Count == 1, CreateBossTankingBehavior(), new SwitchArgument(bool) (adds.Count > 1, CreateAoetankingBehavior())); } When using that script, the CC will always use "CreateAoetankingBehavior()". I tried adding the switch command into "CreateAoetankingBehavior()" and the "CreateBossTankingBehavior()" to determine whether ot not to switch after executing a PrioritySelector. This ended up crashing HB on startup. My original idea would have looked like this: Code: protected Composite CreateBossBehavior() { adds = detectAdds(); return new Switch(int) (ret => adds.Count == 1, CreateBossTankingBehavior(), new SwitchArgument(int) (adds.Count > 1, CreateAoetankingBehavior()) new SwitchArgument(int) (adds.Count > 1 && adds.Count < 6, CreateMegaAoetankingBehavior()) ); } Which does not work, because Switch(T) does not accept "int" as a switch argument. But that would not have changed the problem I'm currently experiencing anyway. All in all, my question is: How can I make the CC evaluate a Switch argument each time a PrioritySelector was run through? I already tried workaraound like adding Code: => ret adds.Count >= 6 to all decorators in the PrioritySelector, but they seem to be ignored. Thank you very much in advance.
heres what i use for zerfall for switching rotations. Code: //PVP SpecSwitch new Decorator(ret => IsBattleGround(), new Switch<WarlockTalentSpec>(r => _talentManager.Spec, new SwitchArgument<WarlockTalentSpec>(Low_rotation(), WarlockTalentSpec.Lowbie), new SwitchArgument<WarlockTalentSpec>(Affliction_PVP(), WarlockTalentSpec.Affliction), new SwitchArgument<WarlockTalentSpec>(Demo_PVP(), WarlockTalentSpec.Demonology), new SwitchArgument<WarlockTalentSpec>(Destro_PVP(), WarlockTalentSpec.Destruction) )), //Instance SpecSwitch new Decorator(ret => Me.IsInInstance && Me.IsInParty, new Switch<WarlockTalentSpec>(r => _talentManager.Spec, new SwitchArgument<WarlockTalentSpec>(Low_rotation(), WarlockTalentSpec.Lowbie), new SwitchArgument<WarlockTalentSpec>(Affliction_Instance(), WarlockTalentSpec.Affliction), new SwitchArgument<WarlockTalentSpec>(Demo_Instance(), WarlockTalentSpec.Demonology), new SwitchArgument<WarlockTalentSpec>(Destro_Instance(), WarlockTalentSpec.Destruction) )), //PVE SpecSwitch if other two fail to be used. new Switch<WarlockTalentSpec>(r => _talentManager.Spec, new SwitchArgument<WarlockTalentSpec>(Low_rotation(), WarlockTalentSpec.Lowbie), new SwitchArgument<WarlockTalentSpec>(Affliction_PVE(), WarlockTalentSpec.Affliction), new SwitchArgument<WarlockTalentSpec>(Demo_PVE(), WarlockTalentSpec.Demonology), new SwitchArgument<WarlockTalentSpec>(Destro_PVE(), WarlockTalentSpec.Destruction) ) i have the most likely first so if im in battlegrounds it will go into that tree first, untill it hits the pve switch the PVE switch is Always going to be used if it dost get sidetracked first. instead of IsBattleground() ,you can always DetectAdds().Count > 2,
Thank you, I'll give it a try Unfortunately, this does not solve my problem of the switch argument only being called once, when the Behaviour is first created.
Finally got the opportunity to test this. The code looks like this: Code: private Composite _combatBehavior; public override Composite CombatBehavior { get { if (_combatBehavior == null) { slog("Creating an awesome Combat behavior"); _combatBehavior = CreateCombatBehavior(); } _combatBehavior = CreateCombatBehavior(); return _combatBehavior; } } private Composite CreateCombatBehavior() { return CreateCombat(); } #endregion #region behaveswitch public Composite CreateCombat() { return new Decorator(ret => Me.IsInInstance && Me.IsInParty, new Switch<TalentSpec>(r => TalentManager.CurrentSpec, new SwitchArgument<TalentSpec>(CreateFuryBehavior(), TalentSpec.FuryWarrior), new SwitchArgument<TalentSpec>(CreateBossBehavior(), TalentSpec.ProtectionWarrior) )); } Unfortunately, the CC now does nothing at all. Both behaviours work when using them without any switch. Any ideas?
are you sure Me.IsInInstance && Me.IsInParty Are returning true? try replacing those with Me.IsAlive or something simple and see if it runs then. </pre>
Yep, figured that out seconds before you replied :/ works perfectly, thanks Have you got any idea how to check for specc intelligently? I put it in pulse, which seems to cause WoW lags.
the problem is the BT is Cached, so it on the fly settings and spec changes wont work. theres no way around it.
You should only need to build the behaviours once -- having them built every pulse is a bad way of doing things. A better way of doing things would be to have a global variable (called CurrentSpec, for example) and check CurrentSpec against TalentManager.CurrentSpec -- if they match, you're the same spec, and if they do not, the spec has changed since the last pulse, so you should rebuild the BehaviorTree with the new spec in mind. e.g: Code: (declare CurrentSpec here) private Composite _CombatBehavior; public override Composite CombatBehavior() { get { if (_CombatBehavior == null) { (enter your code to build your behavior tree for the first time) CurrentSpec = TalentManager.CurrentSpec; } return _CombatBehavior; } public override Pulse() { if (CurrentSpec != TalentManager.CurrentSpec) { CurrentSpec = TalentManager.CurrentSpec; _CombatBehavior = null; } } Something like that should only rebuild the behaviortree if your spec changes. edit: Didn't see above posts before posting, so I suppose my suggestion won't work. Ah well!
Now that I've taken the specccheck out of the pulse, it does not seems to detect speccs at all and therefore does not build any CombatBehaviour :/