/// <summary> /// The created behavior was meant to be used in a PrioritySelector. /// It may also have uses inside other TreeSharp Composites. /// </summary> /// /// <returns> /// <para>* RunStatus.Failure, if swim breath is not needed</para> /// <para>* RunStatus.Success, if we're catching our breath, or moving for it</para> /// </returns> /// public Composite CreateBehavior() { return (_behaviorRoot ?? (_behaviorRoot = new Decorator(ret => Me.IsSwimming, new PrioritySelector( // Moving to, or fetching breath... new Decorator(ret => _isSwimBreathNeeded, new PrioritySelector( // If toon is filling lungs, stay put until full... new Decorator(ret => ((Timer_SwimBreath.ChangePerMillisecond > 0) && (Timer_SwimBreath.CurrentTime < Timer_SwimBreath.MaxValue)), new Action(delegate { WoWMovement.MoveStop(); TreeRoot.StatusText = "Waiting for full breath"; })), // If lungs are full, back to work... new Decorator(ret => (Timer_SwimBreath.CurrentTime >= Timer_SwimBreath.MaxValue), new Action(delegate { _isSwimBreathNeeded = false; })), // Move toon to air source, if needed... new Decorator(ret => { _nearestAirSource = GetNearestAirSource(); return (_nearestAirSource.Distance > Navigator.PathPrecision); }, new Sequence( new DecoratorContinueThrottled(Delay_StatusUpdateThrottle, ret => true, new Action(delegate { TreeRoot.StatusText = string.Format("Moving to {0} for breath. (distance {1:0.0})", _nearestAirSource.Name, _nearestAirSource.Distance); })), new Action(delegate { UnderwaterMoveTo(_nearestAirSource.Location); }) ) ) )), // If we're a Warlock, refresh Unending Breath as needed... new DecoratorThrottled(ThrottleTimer_WarlockBreath, ret => (SpellManager.CanCast(SpellId_WarlockUnendingBreath) && (AuraTimeLeft(AuraName_WarlockUnendingBreath) <= Timer_AuraRefresh_EnduringBreath)), new Action(delegate { SpellManager.Cast(SpellId_WarlockUnendingBreath); })), // If time to breathe, do something about it... new DecoratorThrottled(ThrottleTimer_BreathCheck, ret => IsBreathNeeded(), new PrioritySelector( // If we're a Druid, switch to Aquatic form for breath... new Decorator(ret => (SpellManager.CanCast(SpellId_DruidAquaticForm) && !Me.HasAura(AuraName_DruidAquaticForm)), new Action(delegate { SpellManager.Cast(SpellId_DruidAquaticForm); TreeRoot.StatusText = "Switching to Aquatic Form for breath"; _isSwimBreathNeeded = true; })), // Otherwise, we need to deal with 'normal' way to catch breath... new Action(delegate { _nearestAirSource = GetNearestAirSource(); Logger("info", "Moving to {0} for breath. (distance {1:0.0})", _nearestAirSource.Name, _nearestAirSource.Distance); _isSwimBreathNeeded = true; }) )) )))); }
private AirSource GetNearestAirSource() { // Assume water's surface is nearest breath... AirSource nearestAirSource = new AirSource(Me.Location.WaterSurface(), "water's surface"); WoWObject underwaterAirSource = UnderwaterAirSources.FirstOrDefault(); // If underwater air source exists, and is closer that the water's surface... if ((underwaterAirSource != null) && (Me.Location.Distance(underwaterAirSource.Location) <= nearestAirSource.Distance)) { nearestAirSource.Location = underwaterAirSource.Location; nearestAirSource.Name = underwaterAirSource.Name; } return (nearestAirSource); }