// Empty, for now
        #endregion


        #region Overrides of CustomForcedBehavior

        public override void OnStart()
        {
            // Hunting ground processing...
            // NB: We had to defer this processing from the constructor, because XElement isn't available
            // to parse child XML nodes until OnStart() is called.
            HuntingGrounds      = HuntingGroundsType.GetOrCreate(Element, "HuntingGrounds", HuntingGroundCenter);
            IsAttributeProblem |= HuntingGrounds.IsAttributeProblem;

            // Let QuestBehaviorBase do basic initializaion of the behavior, deal with bad or deprecated attributes,
            // capture configuration state, install BT hooks, etc.  This will also update the goal text.
            OnStart_QuestBehaviorCore(
                string.Format("Using {0} on {1}",
                              GetItemNameFromId(ItemId),
                              string.Join(", ", MobIds.Select(m => GetMobNameFromId(m)).Distinct())));

            // If the quest is complete, this behavior is already done...
            // So we don't want to falsely inform the user of things that will be skipped.
            if (!IsDone)
            {
                ItemToUse = Me.CarriedItems.FirstOrDefault(i => (i.Entry == ItemId));
                if (ItemToUse == null)
                {
                    LogError("[PROFILE ERROR] Unable to locate in our bags", GetItemNameFromId(ItemId));
                    TreeRoot.Stop();
                    BehaviorDone();
                }

                CurrentHuntingGroundWaypoint = HuntingGrounds.FindFirstWaypoint(Me.Location);
            }
        }
Пример #2
0
 private WoWUnit GetNpc()
 {
     return(ObjectManager.GetObjectsOfType <WoWUnit>()
            .Where(
                u => u.IsAlive && MobIds.Contains(((int)u.Entry)) &&
                (u.ThreatInfo.ThreatStatus > ThreatStatus.UnitNotInThreatTable || !Query.IsInCompetition(u, NonCompeteDistance)))
            .OrderBy(u => u.DistanceSqr)
            .FirstOrDefault());
 }
Пример #3
0
        public InteractWith(Dictionary <string, string> args)
            : base(args)
        {
            try
            {
                // QuestRequirement* attributes are explained here...
                //    http://www.thebuddyforum.com/mediawiki/index.php?title=Honorbuddy_Programming_Cookbook:_QuestId_for_Custom_Behaviors
                // ...and also used for IsDone processing.
                WaitForNpcs        = GetAttributeAsBoolean("WaitForNpcs", false, null) ?? true;
                BuyItemCount       = GetAttributeAsInteger("BuyItemCount", false, 1, 1000, null) ?? 1;
                BuyItemId          = GetAttributeAsItemId("BuyItemId", false, null) ?? 0;
                BuySlot            = GetAttributeAsInteger("BuySlot", false, -1, 100, null) ?? -1;
                CollectionDistance = GetAttributeAsInteger("CollectionDistance", false, 1, 10000, null) ?? 100;
                GossipOptions      = GetAttributeAsIntegerArray("GossipOptions", false, -1, 10, new [] { "GossipOption" }) ?? new int[0];
                Loot       = GetAttributeAsBoolean("Loot", false, null) ?? false;
                MobIds     = GetNumberedAttributesAsIntegerArray("MobId", 1, 1, int.MaxValue, new [] { "MobID", "NpcId" }) ?? new int[0];
                ObjType    = GetAttributeAsEnum <ObjectType>("ObjectType", false, new [] { "MobType" }) ?? ObjectType.Npc;
                NotMoving  = GetAttributeAsBoolean("NotMoving", false, null) ?? false;
                NumOfTimes = GetAttributeAsNumOfTimes("NumOfTimes", false, null) ?? 1;
                QuestId    = GetAttributeAsQuestId("QuestId", false, null) ?? 0;
                QuestRequirementComplete = GetAttributeAsEnum <QuestCompleteRequirement>("QuestCompleteRequirement", false, null) ?? QuestCompleteRequirement.NotComplete;
                QuestRequirementInLog    = GetAttributeAsEnum <QuestInLogRequirement>("QuestInLogRequirement", false, null) ?? QuestInLogRequirement.InLog;
                Range    = GetAttributeAsRange("Range", false, null) ?? 4;
                WaitTime = GetAttributeAsWaitTime("WaitTime", false, null) ?? 3000;
                Existing = GetAttributeAsBoolean("Existing", false, null) ?? false;
                Alive    = GetAttributeAsBoolean("Alive", false, null) ?? false;

                for (int i = 0; i < GossipOptions.Length; ++i)
                {
                    GossipOptions[i] -= 1;
                }


                WoWUnit mob = ObjectManager.GetObjectsOfType <WoWUnit>()
                              .Where(unit => MobIds.Contains((int)unit.Entry))
                              .FirstOrDefault();

                MobName = ((mob != null) && !string.IsNullOrEmpty(mob.Name))
                            ? mob.Name
                            : ("Mob(" + MobIds[0] + ")");
            }

            catch (Exception except)
            {
                // Maintenance problems occur for a number of reasons.  The primary two are...
                // * Changes were made to the behavior, and boundary conditions weren't properly tested.
                // * The Honorbuddy core was changed, and the behavior wasn't adjusted for the new changes.
                // In any case, we pinpoint the source of the problem area here, and hopefully it
                // can be quickly resolved.
                UtilLogMessage("error", "BEHAVIOR MAINTENANCE PROBLEM: " + except.Message
                               + "\nFROM HERE:\n"
                               + except.StackTrace + "\n");
                IsAttributeProblem = true;
            }
        }
Пример #4
0
 // Private LINQ queries...
 private IEnumerable <WoWObject> ViableTargets()
 {
     return(ObjectManager.GetObjectsOfType <WoWObject>(true, false)
            .Where(target => (target.IsValid &&
                              MobIds.Contains((int)target.Entry) &&
                              TargetAurasShowing(target, _targetAuraToButtonMap).Any() &&
                              (target.Distance < HuntingGroundRadius) &&
                              !target.IsLocallyBlacklisted() &&
                              !BlacklistIfPlayerNearby(target) &&
                              Query.IsStateMatch_IgnoreMobsInBlackspots(target, IgnoreMobsInBlackspots)))
            .OrderBy(target => Me.Location.SurfacePathDistance(target.Location)));
 }
 // 24Feb2013-08:11UTC chinajade
 private bool IsViableForItemUse(WoWUnit wowUnit)
 {
     return
         (Query.IsViable(wowUnit) &&
          wowUnit.IsAlive &&
          wowUnit.Attackable &&
          MobIds.Contains((int)wowUnit.Entry) &&
          Query.IsViableForInteracting(wowUnit, IgnoreMobsInBlackspots, NonCompeteDistance) &&
          Query.IsViableForPulling(wowUnit, IgnoreMobsInBlackspots, NonCompeteDistance) &&
          (ItemUseAlwaysSucceeds || !wowUnit.HasAura(ItemAppliesAuraId)) &&
          wowUnit.CollectionDistance() <= CollectionDistance);
 }
Пример #6
0
        public BreakImmunityByKillingMobsInCloseProximity(Dictionary <string, string> args)
            : base(args)
        {
            QBCLog.BehaviorLoggingContext = this;

            try
            {
                // QuestRequirement* attributes are explained here...
                //    http://www.thebuddyforum.com/mediawiki/index.php?title=Honorbuddy_Programming_Cookbook:_QuestId_for_Custom_Behaviors
                // ...and also used for IsDone processing.
                // Primary attributes...
                MobIds = GetNumberedAttributesAsArray <int>("MobId", 0, ConstrainAs.MobId, new[] { "NpcId" });
                if (MobIds != null && !MobIds.Any())
                {
                    MobIds = GetAttributeAsArray <int>("MobIds", true, ConstrainAs.MobId, new[] { "NpcIds" }, null);
                }

                ImmunityBreakingMobIds = GetNumberedAttributesAsArray <int>(
                    "ImmunityBreakingMobId",
                    0,
                    ConstrainAs.MobId,
                    new[] { "ImmunityBreakingNpcId" });
                if (ImmunityBreakingMobIds != null && !ImmunityBreakingMobIds.Any())
                {
                    ImmunityBreakingMobIds = GetAttributeAsArray <int>(
                        "ImmunityBreakingMobIds",
                        true,
                        ConstrainAs.MobId,
                        new[] { "ImmunityBreakingNpcIds" },
                        null);
                }

                SearchLocation = GetAttributeAsNullable <Vector3>("", false, ConstrainAs.Vector3NonEmpty, null) ?? Me.Location;

                ImmunityAuraId = GetAttributeAsNullable <int>("ImmunityAuraId", true, ConstrainAs.AuraId, null) ?? 0;
                MaxRange       = GetAttributeAsNullable <double>("MaxRange", false, new ConstrainTo.Domain <double>(0, 40), null) ?? 8;
            }

            catch (Exception except)
            {
                // Maintenance problems occur for a number of reasons.  The primary two are...
                // * Changes were made to the behavior, and boundary conditions weren't properly tested.
                // * The Honorbuddy core was changed, and the behavior wasn't adjusted for the new changes.
                // In any case, we pinpoint the source of the problem area here, and hopefully it
                // can be quickly resolved.
                QBCLog.Exception(except);
                IsAttributeProblem = true;
            }
        }
        public override void OnStart()
        {
            // Let QuestBehaviorBase do basic initializaion of the behavior, deal with bad or deprecated attributes,
            // capture configuration state, install BT hooks, etc.  This will also update the goal text.
            var isBehaviorShouldRun =
                OnStart_QuestBehaviorCore(
                    string.Format("Using {0} on {1}",
                                  Utility.GetItemNameFromId(ItemId),
                                  string.Join(", ", MobIds.Select(m => Utility.GetObjectNameFromId(m)).Distinct())));

            // If the quest is complete, this behavior is already done...
            // So we don't want to falsely inform the user of things that will be skipped.
            if (isBehaviorShouldRun)
            {
                _waitTimerAfterUsingItem.WaitTime = TimeSpan.FromMilliseconds(WaitTimeAfterItemUse);
            }
        }
Пример #8
0
        public CannonControl(Dictionary <string, string> args)
            : base(args)
        {
            QBCLog.BehaviorLoggingContext = this;
            try
            {
                // QuestRequirement* attributes are explained here...
                //    http://www.thebuddyforum.com/mediawiki/index.php?title=Honorbuddy_Programming_Cookbook:_QuestId_for_Custom_Behaviors
                // ...and also used for IsDone processing.
                // Primary attributes...
                MobIds = GetNumberedAttributesAsArray <int>("MobId", 0, ConstrainAs.MobId, new[] { "NpcId" });
                if (MobIds != null && !MobIds.Any())
                {
                    MobIds = GetAttributeAsArray <int>("MobIds", false, ConstrainAs.MobId, new[] { "NpcIds" }, null);
                }
                Buttons               = GetAttributeAsArray <int>("Buttons", true, new ConstrainTo.Domain <int>(1, 12), null, null);
                ExitButton            = GetAttributeAsNullable <int>("ExitButton", false, ConstrainAs.HotbarButton, null) ?? 0;
                MaxAngle              = GetAttributeAsNullable <double>("MaxAngle", false, new ConstrainTo.Domain <double>(-1.5, 1.5), null) ?? 1.5;
                MinAngle              = GetAttributeAsNullable <double>("MinAngle", false, new ConstrainTo.Domain <double>(-1.5, 1.5), null) ?? -1.5;
                Velocity              = GetAttributeAsNullable <double>("Velocity", false, new ConstrainTo.Domain <double>(2.0, 1000), null) ?? 70;
                Gravity               = GetAttributeAsNullable <double>("Gravity", false, new ConstrainTo.Domain <double>(0.01, 80), null) ?? 30;
                VehicleId             = GetAttributeAsNullable <int>("VehicleId", false, ConstrainAs.VehicleId, null) ?? 0;
                VehicleSearchLocation = GetAttributeAsNullable <Vector3>("", false, ConstrainAs.Vector3NonEmpty, null) ?? Me.Location;
                WeaponArticulation    = new WeaponArticulation(MinAngle, MaxAngle);
                Weapons               = Buttons.Select(b => new VehicleWeapon(b, WeaponArticulation, Velocity, Gravity)).ToArray();
            }

            catch (Exception except)
            {
                // Maintenance problems occur for a number of reasons.  The primary two are...
                // * Changes were made to the behavior, and boundary conditions weren't properly tested.
                // * The Honorbuddy core was changed, and the behavior wasn't adjusted for the new changes.
                // In any case, we pinpoint the source of the problem area here, and hopefully it
                // can be quickly resolved.
                QBCLog.Exception(except);
                IsAttributeProblem = true;
            }
        }
Пример #9
0
        protected override Composite CreateBehavior_CombatMain()
        {
            return(new Decorator(context => !IsDone,
                                 new PrioritySelector(

                                     // Update values for this BT node visit...
                                     new Action(context =>
            {
                VehicleUnoccupied = FindUnoccupiedVehicle();

                // Figure out our final destination (i.e., a location or a mob)...
                // NB: this can change as we travel.  If our destination is a mob,
                // We can't "see" distant mobs until we get within 100 yards or so of them.
                // Until we close that distance, we'll head towards the provided location.
                // As soon as we "see" the mob, we'll switch to the mob as the destination.
                FinalDestination = Destination;
                FinalDestinationName = "destination";

                if (MobIds.Count() > 0)
                {
                    // If we can see our destination mob, calculate a path to it...
                    var nearestMob = Query.FindMobsAndFactions(MobIds).OrderBy(u => u.Distance).FirstOrDefault() as WoWUnit;
                    if (nearestMob != null)
                    {
                        // Target destination mob as feedback to the user...
                        Utility.Target(nearestMob);

                        FinalDestination = nearestMob.Location;
                        FinalDestinationName = nearestMob.SafeName;
                    }
                }

                return RunStatus.Failure;           // fall thru
            }),


                                     // Proceed if we're not in combat, or are ignoring it...
                                     new Decorator(context => !Me.Combat || IgnoreCombat,
                                                   new PrioritySelector(
                                                       // If we were successfully mounted...
                                                       // and within a few yards of our destination when we were dismounted, we must
                                                       // assume we were auto-dismounted, and the behavior is complete...
                                                       new Decorator(context => DidSuccessfullyMount && !IsInVehicle() &&
                                                                     (WoWMovement.ActiveMover.Location.Distance(FinalDestination) < 15.0),
                                                                     new Action(context => { BehaviorDone(); })),

                                                       // Enable combat while not in a vehicle
                                                       new Decorator(ctx => (LevelBot.BehaviorFlags & BehaviorFlags.Combat) == 0 && !Query.IsInVehicle(),
                                                                     new Action(ctx => LevelBot.BehaviorFlags |= BehaviorFlags.Combat)),

                                                       // Disable combat while in a vehicle
                                                       new Decorator(ctx => (LevelBot.BehaviorFlags & BehaviorFlags.Combat) != 0 && Query.IsInVehicle(),
                                                                     new Action(ctx => LevelBot.BehaviorFlags &= ~BehaviorFlags.Combat)),

                                                       // If we're not in a vehicle, go fetch one...
                                                       new Decorator(context => !IsInVehicle() && Query.IsViable(VehicleUnoccupied),
                                                                     new Sequence(
                                                                         new CompositeThrottleContinue(
                                                                             Throttle.UserUpdate,
                                                                             new Action(context =>
            {
                TreeRoot.StatusText = string.Format("Moving to {0} {1}",
                                                    VehicleUnoccupied.SafeName,
                                                    Me.Combat ? "(ignoring combat)" : "");
            })),
                                                                         new DecoratorContinue(context => VehicleUnoccupied.WithinInteractRange,
                                                                                               new Action(context => { VehicleUnoccupied.Interact(); })),
                                                                         new ActionRunCoroutine(
                                                                             interactUnitContext => UtilityCoroutine.MoveTo(
                                                                                 VehicleUnoccupied.Location,
                                                                                 VehicleUnoccupied.SafeName,
                                                                                 MovementBy))
                                                                         )),

                                                       // If we can't find a vehicle, terminate if requested...
                                                       new CompositeThrottle(
                                                           context => !IsInVehicle() && !Query.IsViable(VehicleUnoccupied),
                                                           Throttle.UserUpdate,
                                                           new Action(context =>
            {
                if (!WaitForVehicle)
                {
                    BehaviorDone(string.Format("No Vehicle, and WaitForVehicle=\"{0}\"", WaitForVehicle));
                }
                else
                {
                    TreeRoot.StatusText = "No vehicles in area--waiting for vehicle to become available.";
                }
            })),


                                                       // Move vehicle to destination...
                                                       new Decorator(context => IsInVehicle(),
                                                                     new PrioritySelector(
                                                                         // If we successfully mounted the vehicle, record the fact...
                                                                         new Decorator(context => !DidSuccessfullyMount,
                                                                                       new Action(context => { DidSuccessfullyMount = true; })),

                                                                         new Decorator(context => !Navigator.AtLocation(FinalDestination),
                                                                                       new ActionRunCoroutine(
                                                                                           interactUnitContext => UtilityCoroutine.MoveTo(
                                                                                               FinalDestination,
                                                                                               FinalDestinationName,
                                                                                               MovementBy))),

                                                                         new Decorator(context => WoWMovement.ActiveMover.IsMoving,
                                                                                       new Action(context => { WoWMovement.MoveStop(); })),

                                                                         // Arrived at destination, use spell if necessary...
                                                                         // NB: We want to make certain movement is settled before we attempt
                                                                         // to cast spell, so we won't be interrupted.
                                                                         new SleepForLagDuration(),
                                                                         CreateSpellBehavior()
                                                                         ))
                                                       )),

                                     // Squelch combat, if requested...
                                     new Decorator(context => IgnoreCombat,
                                                   new ActionAlwaysSucceed())
                                     )));
        }
Пример #10
0
        protected override Composite CreateBehavior()
        {
            return(_root ??
                   (_root = new PrioritySelector(
                        new Decorator(c => Npc != null,
                                      new Action(c =>
            {
                if (!Npc.Attackable)
                {
                    Blacklist.Add(Npc.Guid, new TimeSpan(0, 5, 0));
                }

                if ((Me.Combat && (Me.GotTarget && Me.CurrentTarget != Npc && !MobIds.Contains((int)Me.CurrentTarget.Entry)) ||
                     Me.HealthPercent < HealthPercent) || IsDone)
                {
                    return RunStatus.Success;
                }
                WoWUnit lootable = ObjectManager.GetObjectsOfType <WoWUnit>().OrderBy(u => u.Distance).
                                   FirstOrDefault(u => u.Lootable);
                if (lootable != null)
                {
                    if (!lootable.WithinInteractRange)
                    {
                        if (Npc.Distance < 30 && SpellManager.CanCast("Death Grip"))
                        {
                            SpellManager.Cast("Death Grip");
                            WoWMovement.MoveStop();
                        }
                        else
                        {
                            Navigator.MoveTo(lootable.Location);
                        }
                    }
                    else
                    {
                        lootable.Interact();
                    }
                    if (Logic.Inventory.Frames.LootFrame.LootFrame.Instance != null &&
                        Logic.Inventory.Frames.LootFrame.LootFrame.Instance.IsVisible)
                    {
                        Logic.Inventory.Frames.LootFrame.LootFrame.Instance.LootAll();
                        if (Me.GotTarget)
                        {
                            Blacklist.Add(Me.CurrentTarget, new TimeSpan(1, 0, 0));
                        }
                        Me.ClearTarget();
                    }
                    return RunStatus.Running;
                }
                if (!Me.GotTarget || Me.CurrentTarget != Npc)
                {
                    Npc.Target();
                }
                if (!Npc.WithinInteractRange)
                {
                    TreeRoot.GoalText = string.Format("Moving to {0}", Npc.Name);
                    Navigator.MoveTo(WoWMathHelper.CalculatePointFrom(Me.Location, Npc.Location, 3));
                }
                else
                {
                    if (Me.IsMoving)
                    {
                        WoWMovement.MoveStop();
                    }
                    if (!Me.IsAutoAttacking || !Me.IsSafelyFacing(ObjectManager.Me.CurrentTarget))
                    {
                        TreeRoot.GoalText = string.Format("Bullying {0}", Npc.Name);
                        Npc.Interact();
                    }
                }
                return RunStatus.Running;
            })),
                        new Action(c => Navigator.MoveTo(Location))
                        )));
        }
Пример #11
0
        protected override Composite CreateBehavior_CombatMain()
        {
            return(new Decorator(context => !IsDone,
                                 new PrioritySelector(

                                     // Update values for this BT node visit...
                                     new Action(context =>
            {
                VehicleUnoccupied = FindUnoccupiedVehicle();

                // Figure out our final destination (i.e., a location or a mob)...
                // NB: this can change as we travel.  If our destination is a mob,
                // We can't "see" distant mobs until we get within 100 yards or so of them.
                // Until we close that distance, we'll head towards the provided location.
                // As soon as we "see" the mob, we'll switch to the mob as the destination.
                FinalDestination = Destination;
                FinalDestinationName = "destination";

                if (MobIds.Count() > 0)
                {
                    // If we can see our destination mob, calculate a path to it...
                    WoWUnit nearestMob = FindUnitsFromIds(MobIds).OrderBy(u => u.Distance).FirstOrDefault();
                    if (nearestMob != null)
                    {
                        // Target destination mob as feedback to the user...
                        if (!Me.GotTarget || (Me.CurrentTarget != nearestMob))
                        {
                            nearestMob.Target();
                        }

                        FinalDestination = nearestMob.Location;
                        FinalDestinationName = nearestMob.Name;
                    }
                }

                return RunStatus.Failure;           // fall thru
            }),


                                     // Proceed if we're not in combat, or are ignoring it...
                                     new Decorator(context => !Me.Combat || IgnoreCombat,
                                                   new PrioritySelector(
                                                       // If we were successfully mounted...
                                                       // and within a few yards of our destination when we were dismounted, we must
                                                       // assume we were auto-dismounted, and the behavior is complete...
                                                       new Decorator(context => DidSuccessfullyMount && !IsInVehicle() &&
                                                                     (Me.Location.Distance(FinalDestination) < 15.0),
                                                                     new Action(context => { BehaviorDone(); })),

                                                       // If we're not in a vehicle, go fetch one...
                                                       new Decorator(context => !IsInVehicle() && IsViable(VehicleUnoccupied),
                                                                     new Sequence(
                                                                         new Action(context =>
            {
                TreeRoot.StatusText = string.Format("Moving to {0} {1}",
                                                    VehicleUnoccupied.Name,
                                                    Me.Combat ? "(ignoring combat)" : "");
            }),
                                                                         new DecoratorContinue(context => VehicleUnoccupied.WithinInteractRange,
                                                                                               new Action(context => { VehicleUnoccupied.Interact(); })),
                                                                         UtilityBehaviorPS_MoveTo(context => VehicleUnoccupied.Location,
                                                                                                  context => VehicleUnoccupied.Name)
                                                                         )),

                                                       // If we successfully mounted the vehicle, record the fact...
                                                       new Decorator(context => IsInVehicle() && !DidSuccessfullyMount,
                                                                     new Action(context => { DidSuccessfullyMount = true; })),

                                                       // Move vehicle to destination...
                                                       UtilityBehaviorPS_MoveTo(context => FinalDestination,
                                                                                context => FinalDestinationName,
                                                                                context => Precision,
                                                                                context => IsInVehicle(),
                                                                                context => LocationObserver()),
                                                       new Decorator(context => Me.IsMoving,
                                                                     new Sequence(
                                                                         new Action(context => { WoWMovement.MoveStop(); }),
                                                                         new WaitContinue(TimeSpan.FromMilliseconds(CastTime), context => false, new ActionAlwaysSucceed())
                                                                         )),

                                                       // Arrived at destination, use spell if necessary...
                                                       CreateSpellBehavior()
                                                       )),

                                     // Squelch combat, if requested...
                                     new Decorator(context => IgnoreCombat,
                                                   new ActionAlwaysSucceed())
                                     )));
        }
Пример #12
0
        public InteractWith(Dictionary <string, string> args)
            : base(args)
        {
            try
            {
                // Warn of deprecated attributes...
                if (args.ContainsKey("BuySlot"))
                {
                    LogMessage("warning", "*****\n"
                               + "* THE BUYSLOT ATTRIBUTE IS DEPRECATED, and may be retired in a near, future release.\n"
                               + "*\n"
                               + "* BuySlot presents a number of problems.  If a vendor presents 'seasonal' or\n"
                               + "* limited-quantity wares, the slot number for the desired item can change.\n"
                               + "\n"
                               + "* Please update the profile to use *BuyItemId* attribute in preference to BuySlot.\n"
                               + "*****");
                }

                // QuestRequirement* attributes are explained here...
                //    http://www.thebuddyforum.com/mediawiki/index.php?title=Honorbuddy_Programming_Cookbook:_QuestId_for_Custom_Behaviors
                // ...and also used for IsDone processing.
                BuyItemCount       = GetAttributeAsNullable <int>("BuyItemCount", false, ConstrainAs.CollectionCount, null) ?? 1;
                BuyItemId          = GetAttributeAsNullable <int>("BuyItemId", false, ConstrainAs.ItemId, null) ?? 0;
                BuySlot            = GetAttributeAsNullable <int>("BuySlot", false, new ConstrainTo.Domain <int>(-1, 100), null) ?? -1;
                CollectionDistance = GetAttributeAsNullable <double>("CollectionDistance", false, ConstrainAs.Range, null) ?? 100;
                GossipOptions      = GetAttributeAsArray <int>("GossipOptions", false, new ConstrainTo.Domain <int>(-1, 10), new[] { "GossipOption" }, null);
                Location           = GetAttributeAsNullable <WoWPoint>("", false, ConstrainAs.WoWPointNonEmpty, null) ?? Me.Location;
                Loot                     = GetAttributeAsNullable <bool>("Loot", false, null, null) ?? false;
                MobIds                   = GetNumberedAttributesAsArray <int>("MobId", 1, ConstrainAs.MobId, new[] { "NpcId" });
                ObjType                  = GetAttributeAsNullable <ObjectType>("ObjectType", false, null, new[] { "MobType" }) ?? ObjectType.Npc;
                NpcState                 = GetAttributeAsNullable <NpcStateType>("MobState", false, null, new[] { "NpcState" }) ?? NpcStateType.DontCare;
                NavigationState          = GetAttributeAsNullable <NavigationType>("Nav", false, null, new[] { "Navigation" }) ?? NavigationType.Mesh;
                MobHpPercentLeft         = GetAttributeAsNullable <double>("MobHpPercentLeft", false, ConstrainAs.Percent, new[] { "HpLeftAmount" }) ?? 100.0;
                NotMoving                = GetAttributeAsNullable <bool>("NotMoving", false, null, null) ?? false;
                NumOfTimes               = GetAttributeAsNullable <int>("NumOfTimes", false, ConstrainAs.RepeatCount, null) ?? 1;
                QuestId                  = GetAttributeAsNullable("QuestId", false, ConstrainAs.QuestId(this), null) ?? 0;
                QuestRequirementComplete = GetAttributeAsNullable <QuestCompleteRequirement>("QuestCompleteRequirement", false, null, null) ?? QuestCompleteRequirement.NotComplete;
                QuestRequirementInLog    = GetAttributeAsNullable <QuestInLogRequirement>("QuestInLogRequirement", false, null, null) ?? QuestInLogRequirement.InLog;
                Range                    = GetAttributeAsNullable <double>("Range", false, ConstrainAs.Range, null) ?? 4.0;
                WaitForNpcs              = GetAttributeAsNullable <bool>("WaitForNpcs", false, null, null) ?? true;
                WaitTime                 = GetAttributeAsNullable <int>("WaitTime", false, ConstrainAs.Milliseconds, null) ?? 3000;
                IgnoreCombat             = GetAttributeAsNullable <bool>("IgnoreCombat", false, null, null) ?? false;

                for (int i = 0; i < GossipOptions.Length; ++i)
                {
                    GossipOptions[i] -= 1;
                }


                IEnumerable <WoWUnit> mobs = ObjectManager.GetObjectsOfType <WoWUnit>(true, false)
                                             .Where(unit => MobIds.Contains((int)unit.Entry));

                MobNames = string.Join(", ", mobs.Select(mob => (!string.IsNullOrEmpty(mob.Name)
                                                                ? mob.Name
                                                                : ("Mob(" + mob.Entry.ToString() + ")")))
                                       .ToArray());
            }

            catch (Exception except)
            {
                // Maintenance problems occur for a number of reasons.  The primary two are...
                // * Changes were made to the behavior, and boundary conditions weren't properly tested.
                // * The Honorbuddy core was changed, and the behavior wasn't adjusted for the new changes.
                // In any case, we pinpoint the source of the problem area here, and hopefully it
                // can be quickly resolved.
                LogMessage("error", "BEHAVIOR MAINTENANCE PROBLEM: " + except.Message
                           + "\nFROM HERE:\n"
                           + except.StackTrace + "\n");
                IsAttributeProblem = true;
            }
        }