// Largely used to convert 'string' representation of a value into the value's type... public object ToCongruentObject(object value) { var backingType = PropInfo.PropertyType; var providedType = value != null?value.GetType() : backingType; try { Type underlyingType = Nullable.GetUnderlyingType(backingType); if (underlyingType != null) { // Nullables are treated specially as they can be assigned from a null reference or just an underlying value return(value != null?Convert.ChangeType(value, underlyingType, CultureInfo.InvariantCulture) : null); } // Disallow int => bool conversions... // These are almost _always_ mistakes on the profile writer's part. if ((providedType == typeof(int) && (backingType == typeof(bool)))) { throw new ArgumentException(); } return(Convert.ChangeType(value, backingType, CultureInfo.InvariantCulture)); } catch (Exception) { var message = string.Format("For setting '{0}', the provided value '{1}' ({2})" + " cannot be converted to the backing type ({3}).", Name, value ?? "(NULL)", providedType.Name, backingType.Name); QBCLog.Error(message); throw new ArgumentException(message); } }
// 11Apr2013-04:42UTC chinajade public static HuntingGroundsType GetOrCreate(XElement parentElement, string elementName, WaypointType defaultHuntingGroundCenter = null, double?forcedTolerance = null) { var huntingGrounds = new HuntingGroundsType(parentElement .Elements() .DefaultIfEmpty(new XElement(elementName)) .FirstOrDefault(elem => (elem.Name == elementName))); if (!huntingGrounds.IsAttributeProblem) { if (forcedTolerance.HasValue) { foreach (var waypoint in huntingGrounds.Waypoints) { waypoint.ArrivalTolerance = forcedTolerance.Value; } } // If user didn't provide a HuntingGrounds, and he provided a default center point, add it... if (!huntingGrounds.Waypoints.Any() && (defaultHuntingGroundCenter != null)) { huntingGrounds.Waypoints.Add(defaultHuntingGroundCenter); } if (!huntingGrounds.Waypoints.Any()) { QBCLog.Error("Neither the X/Y/Z attributes nor the <{0}> sub-element has been specified.", elementName); huntingGrounds.IsAttributeProblem = true; } } return(huntingGrounds); }
public EquipmentType(XElement xElement) : base(xElement) { try { ItemId = GetAttributeAsNullable <int>("ItemId", true, ConstrainAs.ItemId, null) ?? 0; Name = GetAttributeAs <string>("Name", false, ConstrainAs.StringNonEmpty, null) ?? string.Empty; if (string.IsNullOrEmpty(Name)) { Name = GetDefaultName(ItemId); } HandleAttributeProblem(); } catch (Exception except) { if (Query.IsExceptionReportingNeeded(except)) { QBCLog.Error("[PROFILE PROBLEM with \"{0}\"]: {1}\nFROM HERE ({2}):\n{3}\n", xElement.ToString(), except.Message, except.GetType().Name, except.StackTrace); } IsAttributeProblem = true; } }
public MobType(XElement xElement) : base(xElement) { try { Name = GetAttributeAs <string>("Name", false, ConstrainAs.StringNonEmpty, null) ?? string.Empty; Entry = GetAttributeAsNullable <int>("Entry", false, ConstrainAs.MobId, null) ?? GetAttributeAsNullable <int>("Id", false, ConstrainAs.MobId, null) ?? 0; if (Entry == 0) { QBCLog.Error(QBCLog.BuildMessageWithContext(Element, "Attribute '{1}' is required, but was not provided.", Environment.NewLine, "Entry")); IsAttributeProblem = true; } HandleAttributeProblem(); } catch (Exception except) { if (Query.IsExceptionReportingNeeded(except)) { QBCLog.Exception(except, "PROFILE PROBLEM with \"{0}\"", xElement.ToString()); } IsAttributeProblem = true; } }
// 11Apr2013-04:42UTC chinajade public static SafePathType GetOrCreate(XElement parentElement, string elementName, double defaultEgressDistance, Vector3?safespotLocation = null) { if (safespotLocation.HasValue && ((safespotLocation.Value == Vector3.Zero) || safespotLocation.Value == Vector3.Zero)) { safespotLocation = null; } var safePath = new SafePathType(parentElement .Elements() .DefaultIfEmpty(new XElement(elementName)) .FirstOrDefault(elem => (elem.Name == elementName)), defaultEgressDistance); if (!safePath.IsAttributeProblem) { // If user didn't provide a HuntingGrounds, and he provided a default center point, add it... if (!safePath.Waypoints.Any() && safespotLocation.HasValue) { safePath.Waypoints.Add(new WaypointType(safespotLocation.Value, "safe spot", 7.0)); } if (!safePath.Waypoints.Any()) { QBCLog.Error("Neither the X/Y/Z attributes nor the <{0}> sub-element has been specified.", elementName); safePath.IsAttributeProblem = true; } } return(safePath); }
public override void OnStart() { PlayerQuest quest = StyxWoW.Me.QuestLog.GetQuestById((uint)QuestId); if ((QuestId != 0) && (quest == null)) { QBCLog.Error("This behavior has been associated with QuestId({0}), but the quest is not in our log", QuestId); IsAttributeProblem = true; } // This reports problems, and stops BT processing if there was a problem with attributes... // We had to defer this action, as the 'profile line number' is not available during the element's // constructor call. OnStart_HandleAttributeProblem(); // 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) { _configMemento = new ConfigMemento(); // Disable any settings that may interfere with the escort -- // When we escort, we don't want to be distracted by other things. // NOTE: these settings are restored to their normal values when the behavior completes // or the bot is stopped. CharacterSettings.Instance.PullDistance = 25; GlobalSettings.Instance.KillBetweenHotspots = true; _behaviorTreeCombatHook = CreateCombatBehavior(); TreeHooks.Instance.InsertHook("Combat_Only", 0, _behaviorTreeCombatHook); this.UpdateGoalText(QuestId); } }
public T[] GetAttributeAsArray <T>(string attributeName, bool isAttributeRequired, IConstraintChecker <T> constraints, string[] attributeNameAliases, char[] separatorCharacters) { // Vector3 are triples, so requires special handling... if (typeof(T) == typeof(Vector3)) { return((T[])UtilGetAttributeAsVector3s(attributeName, isAttributeRequired, attributeNameAliases)); } constraints = constraints ?? new ConstrainTo.Anything <T>(); separatorCharacters = separatorCharacters ?? new[] { ' ', ',', ';' }; bool isError = false; string keyName = UtilLocateKey(isAttributeRequired, attributeName, attributeNameAliases); var resultList = new List <T>(); if ((keyName == null) || !Attributes.ContainsKey(keyName)) { resultList.Clear(); return(resultList.ToArray()); } // We 'continue' even if problems are encountered... // By doing this, the profile writer can see all his mistakes at once, rather than being // nickel-and-dimed to death with error messages. foreach (string listEntry in Attributes[keyName].Split(separatorCharacters, StringSplitOptions.RemoveEmptyEntries)) { T tmpResult; try { tmpResult = UtilTo <T>(keyName, listEntry); } catch (Exception) { isError = true; continue; } string constraintViolationMessage = constraints.Check(keyName, tmpResult); if (constraintViolationMessage != null) { QBCLog.Error(QBCLog.BuildMessageWithContext(Element, constraintViolationMessage)); isError = true; continue; } resultList.Add(tmpResult); } if (isError) { resultList.Clear(); IsAttributeProblem = true; } return(resultList.ToArray()); }
public T[] GetNumberedAttributesAsArray <T>(string baseName, int countRequired, IConstraintChecker <T> constraints, IEnumerable <string> aliasBaseNames) { bool isError = false; bool isVector3 = (typeof(T) == typeof(Vector3)); var resultList = new List <T>(); // Search for primary names first -- // We 'continue' even if problems are encountered. By doing this, the profile writer can see // all his mistakes at once, rather than being nickel-and-dimed to death with error messages. var primaryAttributeNames = from attributeName in Attributes.Keys where UtilIsNumberedAttribute(baseName, attributeName, isVector3) select attributeName; foreach (var numberedAttributeName in primaryAttributeNames) { isError |= UtilAddToNumberedAttributeToArray <T>(numberedAttributeName, constraints, resultList); } // Search using alias names -- // We 'continue' even if problems are encountered. By doing this, the profile writer can see // all his mistakes at once, rather than being nickel-and-dimed to death with error messages. if (aliasBaseNames != null) { var aliasAttributeNames = from aliasBaseName in aliasBaseNames from attributeName in Attributes.Keys where UtilIsNumberedAttribute(aliasBaseName, attributeName, isVector3) select attributeName; foreach (var numberedAttributeName in aliasAttributeNames) { isError |= UtilAddToNumberedAttributeToArray <T>(numberedAttributeName, constraints, resultList); } } if (resultList.Count < countRequired) { QBCLog.Error(QBCLog.BuildMessageWithContext(Element, "The attribute '{1}N' must be provided at least {2} times (saw it '{3}' times).{0}" + "(E.g., ButtonText1, ButtonText2, ButtonText3, ...){0}" + "Please modify to supply {2} attributes with a base name of '{1}'.", Environment.NewLine, baseName, countRequired, resultList.Count)); isError = true; } if (isError) { resultList.Clear(); IsAttributeProblem = true; } return(resultList.ToArray()); }
public override void OnStart() { PlayerQuest quest = StyxWoW.Me.QuestLog.GetQuestById((uint)QuestId); if ((QuestId != 0) && (quest == null)) { QBCLog.Error("This behavior has been associated with QuestId({0}), but the quest is not in our log", QuestId); IsAttributeProblem = true; } // This reports problems, and stops BT processing if there was a problem with attributes... // We had to defer this action, as the 'profile line number' is not available during the element's // constructor call. OnStart_HandleAttributeProblem(); // We need to move off boat after quest is complete, so we can't use "quest complete" // as part of the normal IsDone criteria for this behavior. So, we explicitly check for // quest complete here, and set IsDone appropriately. if (!UtilIsProgressRequirementsMet(QuestId, QuestRequirementInLog, QuestRequirementComplete)) { _isBehaviorDone = true; } // 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) { _configMemento = new ConfigMemento(); // Disable any settings that may interfere with the escort -- // When we escort, we don't want to be distracted by other things. // NOTE: these settings are restored to their normal values when the behavior completes // or the bot is stopped. CharacterSettings.Instance.HarvestHerbs = false; CharacterSettings.Instance.HarvestMinerals = false; CharacterSettings.Instance.LootChests = false; CharacterSettings.Instance.NinjaSkin = false; CharacterSettings.Instance.SkinMobs = false; BlackspotManager.AddBlackspots(Blackspots); State_MainBehavior = StateType_MainBehavior.AssigningTask; _behaviorTreeHook_CombatMain = CreateBehavior_CombatMain(); TreeHooks.Instance.InsertHook("Combat_Main", 0, _behaviorTreeHook_CombatMain); _behaviorTreeHook_CombatOnly = CreateBehavior_CombatOnly(); TreeHooks.Instance.InsertHook("Combat_Only", 0, _behaviorTreeHook_CombatOnly); _behaviorTreeHook_DeathMain = CreateBehavior_DeathMain(); TreeHooks.Instance.InsertHook("Death_Main", 0, _behaviorTreeHook_DeathMain); this.UpdateGoalText(QuestId); } }
protected override async Task <ActivityResult> ExecuteSpecificActivity() { // If spell is not known at the moment, this is a problem... if ((_wowSpell == null) || !_wowSpell.IsValid) { QBCLog.Error(_errorMessage_UnknownSpell); return(ActivityResult.Failed); } return (await UtilityCoroutine.CastSpell(_wowSpell.Id) == SpellCastResult.Succeeded ? ActivityResult.Succeeded : ActivityResult.Failed); }
public VehicleMover(Dictionary <string, string> args) : base(args) { try { // NB: Core attributes are parsed by QuestBehaviorBase parent (e.g., QuestId, NonCompeteDistance, etc) // Primary attributes... AuraId_ProxyVehicle = GetAttributeAsNullable <int>("AuraId_ProxyVehicle", false, ConstrainAs.SpellId, null) ?? 0; MobIds = GetNumberedAttributesAsArray <int>("MobId", 0, ConstrainAs.MobId, new[] { "MobID", "NpcId" }); SpellId = GetAttributeAsNullable <int>("SpellId", false, ConstrainAs.SpellId, new[] { "SpellID" }) ?? 0; VehicleIds = GetNumberedAttributesAsArray <int>("VehicleId", 1, ConstrainAs.VehicleId, new[] { "VehicleID" }); Destination = GetAttributeAsNullable <WoWPoint>("", true, ConstrainAs.WoWPointNonEmpty, null) ?? WoWPoint.Empty; // Tunables... NumOfTimes = GetAttributeAsNullable <int>("CastNum", false, ConstrainAs.RepeatCount, null) ?? 1; CastTime = GetAttributeAsNullable <int>("CastTime", false, new ConstrainTo.Domain <int>(0, 30000), null) ?? 1500; Hop = GetAttributeAsNullable <bool>("Hop", false, null, null) ?? false; IgnoreCombat = GetAttributeAsNullable <bool>("IgnoreCombat", false, null, null) ?? true; /*unused*/ GetAttributeAsNullable <double>("Precision", false, new ConstrainTo.Domain <double>(2.0, 100.0), null); var useNavigator = GetAttributeAsNullable <bool>("UseNavigator", false, null, null); if (useNavigator.HasValue) { MovementBy = useNavigator.Value ? MovementByType.NavigatorPreferred : MovementByType.ClickToMoveOnly; } WaitForVehicle = GetAttributeAsNullable <bool>("WaitForVehicle", false, null, null) ?? true; // For backward compatibility, we do not error off on an invalid SpellId, but merely warn the user... if ((1 <= SpellId) && (SpellId <= 12)) { QBCLog.Error("SpellId of {0} is not valid--did you accidently provde an ActionBarIndex instead?", SpellId); } } 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; } }
private void ActionRemove() { var activityIdentifier = FindActivityIdentifier(); var activity = FindActivity(activityIdentifier); // If activity does not exist, that's a problem... if (activity == null) { QBCLog.Error("DoWhenActivity '{0}' is not in use.", activityIdentifier); return; } // Remove the activity... s_persistedActivities.Remove(activity); QBCLog.DeveloperInfo("DoWhenActivity '{0}' removed.", activity.ActivityIdentifier); }
private async Task <bool> MainCoroutine() { if (!string.IsNullOrEmpty(CurrentProfileName)) { QBCLog.Info("Skipping Current HBRelogTask... Bye Bye Now"); HBRelogRemoteApi.SkipCurrentTask(CurrentProfileName); BehaviorDone(); return(true); } else { QBCLog.Error("Could not connect to HBRelog Server or Invalid Profile. Could not Skip Task"); BehaviorDone(); return(true); } }
public override void OnStart() { PlayerQuest quest = StyxWoW.Me.QuestLog.GetQuestById((uint)QuestId); if ((QuestId != 0) && (quest == null)) { QBCLog.Error("This behavior has been associated with QuestId({0}), but the quest is not in our log", QuestId); IsAttributeProblem = true; } // This reports problems, and stops BT processing if there was a problem with attributes... // We had to defer this action, as the 'profile line number' is not available during the element's // constructor call. OnStart_HandleAttributeProblem(); // 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) { _configMemento = new ConfigMemento(); // Disable any settings that may interfere with the escort -- // When we escort, we don't want to be distracted by other things. // NOTE: these settings are restored to their normal values when the behavior completes // or the bot is stopped. CharacterSettings.Instance.HarvestHerbs = false; CharacterSettings.Instance.HarvestMinerals = false; CharacterSettings.Instance.LootChests = false; CharacterSettings.Instance.NinjaSkin = false; CharacterSettings.Instance.SkinMobs = false; // CharacterSettings.Instance.PullDistance = 1; // don't pull anything unless we absolutely must BlackspotManager.AddBlackspots(Blackspots); State_MainBehavior = StateType_MainBehavior.DroppingOffVictim; _behaviorTreeHook_CombatMain = CreateBehavior_CombatMain(); TreeHooks.Instance.InsertHook("Combat_Main", 0, _behaviorTreeHook_CombatMain); _behaviorTreeHook_CombatOnly = CreateBehavior_CombatOnly(); TreeHooks.Instance.InsertHook("Combat_Only", 0, _behaviorTreeHook_CombatOnly); _behaviorTreeHook_DeathMain = CreateBehavior_DeathMain(); TreeHooks.Instance.InsertHook("Death_Main", 0, _behaviorTreeHook_DeathMain); this.UpdateGoalText(QuestId); } }
protected override async Task <ActivityResult> ExecuteSpecificActivity() { // If item is not in inventory at the moment, we consider that a problem... if (!Query.IsViable(_itemToUse)) { QBCLog.Error(_errorMessage_ItemNotInInventory); return(ActivityResult.Failed); } var activityResult = ActivityResult.Failed; await UtilityCoroutine.UseItem((int)_itemToUse.Entry, null, /*missing item is non-fatal*/ null, /*notification on fail*/ () => { activityResult = ActivityResult.Succeeded; }); return(activityResult); }
public CombatUseItemOn(Dictionary <string, string> args) : base(args) { QBCLog.BehaviorLoggingContext = this; try { CastingSpellId = GetAttributeAsNullable <int>("CastingSpellId", false, ConstrainAs.SpellId, null) ?? 0; MaxRange = GetAttributeAsNullable <double>("MaxRange", false, ConstrainAs.Range, null) ?? 25; HasAuraId = GetAttributeAsNullable <int>("HasAuraId", false, ConstrainAs.AuraId, new[] { "HasAura" }) ?? 0; ItemId = GetAttributeAsNullable <int>("ItemId", true, ConstrainAs.ItemId, null) ?? 0; Location = GetAttributeAsNullable <Vector3>("", false, ConstrainAs.Vector3NonEmpty, null) ?? Me.Location; MobIds = GetNumberedAttributesAsArray <int>("MobId", 1, ConstrainAs.MobId, new[] { "NpcId" }); MobHasAuraId = GetAttributeAsNullable <int>("MobHasAuraId", false, ConstrainAs.AuraId, new[] { "NpcHasAuraId", "NpcHasAura" }) ?? 0; MobHpPercentLeft = GetAttributeAsNullable <double>("MobHpPercentLeft", false, ConstrainAs.Percent, new[] { "NpcHpLeft", "NpcHPLeft" }) ?? 0; NumOfTimes = GetAttributeAsNullable <int>("NumOfTimes", false, ConstrainAs.RepeatCount, null) ?? 1; QuestId = GetAttributeAsNullable <int>("QuestId", false, ConstrainAs.QuestId(this), null) ?? 0; UseOnce = GetAttributeAsNullable <bool>("UseOnce", false, null, null) ?? true; BlacklistMob = GetAttributeAsNullable <bool>("BlacklistMob", false, null, null) ?? false; WaitTime = GetAttributeAsNullable <int>("WaitTime", false, ConstrainAs.Milliseconds, null) ?? 500; QuestRequirementComplete = GetAttributeAsNullable <QuestCompleteRequirement>("QuestCompleteRequirement", false, null, null) ?? QuestCompleteRequirement.NotComplete; QuestRequirementInLog = GetAttributeAsNullable <QuestInLogRequirement>("QuestInLogRequirement", false, null, null) ?? QuestInLogRequirement.InLog; // semantic coherency checks -- if ((CastingSpellId == 0) && (HasAuraId == 0) && (MobHasAuraId == 0) && (MobHpPercentLeft == 0.0)) { QBCLog.Error("One or more of the following attributes must be specified:\n" + "CastingSpellId, HasAuraId, MobHasAuraId, MobHpPercentLeft"); IsAttributeProblem = true; } QuestBehaviorBase.DeprecationWarning_Behavior(this, "CombatUseItemOnV2", BuildReplacementArguments()); } 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; } }
private void UtilPopulateMapWithAuras(Dictionary <int, int> auraIdToButtonMap, int buttonNum, int[] auraIds) { foreach (int auraId in auraIds) { if (auraIdToButtonMap.ContainsKey(auraId)) { QBCLog.Error("AuraId({0}) cannot be associated with two buttons." + " (Attempted to associate with Button{1} and Button{2}.)", auraId, auraIdToButtonMap[auraId], buttonNum); IsAttributeProblem = true; break; } auraIdToButtonMap.Add(auraId, buttonNum); } }
public override void OnStart() { var questId = GetQuestId(); PlayerQuest quest = StyxWoW.Me.QuestLog.GetQuestById((uint)questId); if ((questId != 0) && (quest == null)) { QBCLog.Error("This behavior has been associated with QuestId({0}), but the quest is not in our log", questId); IsAttributeProblem = true; } // If the needed item is not in my inventory, report problem... if (!Me.BagItems.Any(i => ItemId_BlindingRageTrap == (int)i.Entry)) { QBCLog.Error("The behavior requires \"Blind Rage Trap\"(ItemId: {0}) to be in our bags; however, it cannot be located)", ItemId_BlindingRageTrap); IsAttributeProblem = true; } // Let QuestBehaviorBase do basic initialization 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(); // 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) { // Disable any settings that may interfere with the escort -- // When we escort, we don't want to be distracted by other things. // NOTE: these settings are restored to their normal values when the behavior completes // or the bot is stopped. CharacterSettings.Instance.HarvestHerbs = false; CharacterSettings.Instance.HarvestMinerals = false; CharacterSettings.Instance.LootChests = false; CharacterSettings.Instance.NinjaSkin = false; CharacterSettings.Instance.SkinMobs = false; // don't pull anything unless we absolutely must LevelBot.BehaviorFlags &= ~BehaviorFlags.Pull; _combatContext = new BattlefieldContext(ItemId_BlindingRageTrap, GameObjectId_BlindingRageTrap); this.UpdateGoalText(GetQuestId(), "Looting and Harvesting are disabled while behavior in progress"); } }
private IEnumerable <WoWUnit> FindUnitsFromIds(params int[] unitIds) { if (unitIds == null) { string message = "BEHAVIOR MAINTENANCE ERROR: unitIds argument may not be null"; QBCLog.Error(message); throw new ArgumentException(message); } return (from unit in ObjectManager.GetObjectsOfType <WoWUnit>() where unit.IsValid && unit.IsAlive && unitIds.Contains((int)unit.Entry) && !unit.TaggedByOther select unit); }
public async Task <bool> Execute() { if (!IsSpecificExecutionNeeded()) { return(false); } if (IsMovementStopRequired && Me.IsMoving) { await CommonCoroutines.StopMoving(); } var activityResult = await ExecuteSpecificActivity(); if (activityResult == ActivityResult.Indeterminate) { return(ShouldBreakWhenIndeterminate); } if (activityResult == ActivityResult.Failed) { return(false); } // If we get here, we got a ActivityResult.Succeeded UseWhenPredicate.Reset(); // If predicate did not clear, then predicate is bad... // We allow for a server round-trip time to allow enough time for a potential // aura to be applied. await CommonCoroutines.SleepForLagDuration(); if (UseWhenPredicate.IsReady()) { QBCLog.Error( "For DoWhenActivity {1}, predicate ({2}) was not reset by execution.{0}" + " This is a profile problem, and can result in erratic Honorbuddy behavior.{0}" + " The predicate must return to 'false' after the action has been successfully executed.", Environment.NewLine, ActivityIdentifier, UseWhenPredicate.ExpressionAsString); } return(true); }
public void SetValue(object newValueAsObject) { if (IsAccessDisallowed) { return; } var newValue = ToCongruentObject(newValueAsObject); if (!ConstraintChecker.IsWithinConstraints(newValue)) { var message = string.Format("For '{0}', provided value ('{1}') is not within required constraints {2}.", Name, newValue, ConstraintChecker.Description); QBCLog.Error(message); throw new ArgumentException(message); } PropInfo.SetValue(SettingsInstance, newValue, null); }
private object UtilGetAttributeAs <T>(string attributeName, bool isAttributeRequired, IConstraintChecker <T> constraints, string[] attributeNameAliases) { Type concreteType = typeof(T); // Vector3 are a triple of attributes, so requires special handling... if (concreteType == typeof(Vector3)) { return(UtilGetXYZAttributesAsVector3(attributeName, isAttributeRequired, attributeNameAliases)); } constraints = constraints ?? new ConstrainTo.Anything <T>(); string keyName = UtilLocateKey(isAttributeRequired, attributeName, attributeNameAliases); if ((keyName == null) || !Attributes.ContainsKey(keyName)) { return(null); } T tmpResult; string valueAsString = Attributes[keyName]; try { tmpResult = UtilTo <T>(keyName, valueAsString); } catch (Exception) { IsAttributeProblem = true; return(null); } string constraintViolationMessage = constraints.Check(keyName, tmpResult); if (constraintViolationMessage != null) { QBCLog.Error(QBCLog.BuildMessageWithContext(Element, constraintViolationMessage)); IsAttributeProblem = true; return(null); } return(tmpResult); }
protected PursueObjectTypeBase(XElement xElement, string parameterName, Type expressionType) : base(xElement) { try { Id = GetAttributeAsNullable <int>("Id", false, ConstrainAs.MobId, null) ?? 0; Priority = GetAttributeAsNullable <int>("Priority", false, new ConstrainTo.Domain <int>(-10000, 10000), null) ?? 0; var pursueWhenExpression = GetAttributeAs <string>("PursueWhen", false, ConstrainAs.StringNonEmpty, null); var convertWhenExpression = GetAttributeAs <string>("ConvertWhen", false, ConstrainAs.StringNonEmpty, null) ?? "false"; ConvertBy = GetAttributeAsNullable <ConvertByType>("ConvertBy", false, null, null) ?? ConvertByType.Killing; if (string.IsNullOrEmpty(pursueWhenExpression)) { if (Id == 0) { QBCLog.Error("Either Id, PursueWhen, or both must be specified."); IsAttributeProblem = true; } else { pursueWhenExpression = "true"; } } ConvertWhenDelayCompiledExpression = (DelayCompiledExpression)Activator.CreateInstance(expressionType, parameterName + "=>" + convertWhenExpression); ConvertWhen = ConvertWhenDelayCompiledExpression.CallableExpression; PursueWhenDelayCompiledExpression = (DelayCompiledExpression)Activator.CreateInstance(expressionType, parameterName + "=>" + pursueWhenExpression); PursueWhen = PursueWhenDelayCompiledExpression.CallableExpression; } catch (Exception except) { if (Query.IsExceptionReportingNeeded(except)) { QBCLog.Exception(except, "PROFILE PROBLEM with \"{0}\"", xElement.ToString()); } IsAttributeProblem = true; } }
private void ActionSetEnableState(bool wantEnabled) { var activityIdentifier = FindActivityIdentifier(); var activity = FindActivity(activityIdentifier); // If activity does not exist, that's a problem... if (activity == null) { QBCLog.Error("DoWhenActivity '{0}' is not in use.", activityIdentifier); return; } // Update activity's enabled status... var previousState = activity.UseWhenPredicate.IsEnabled; activity.UseWhenPredicate.IsEnabled = wantEnabled; QBCLog.DeveloperInfo("DoWhenActivity '{0}' {1} (was {2}).", activity.ActivityIdentifier, (wantEnabled ? "enabled" : "disabled"), (previousState ? "enabled" : "disabled")); }
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(); // 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) { HbProcId = System.Diagnostics.Process.GetCurrentProcess().Id; _pipeFactory = new ChannelFactory <IRemotingApi>(new NetNamedPipeBinding(), new EndpointAddress("net.pipe://localhost/HBRelog/Server")); try { HBRelogRemoteApi = _pipeFactory.CreateChannel(); IsConnected = HBRelogRemoteApi.Init(HbProcId); if (IsConnected) { QBCLog.DeveloperInfo("Connected to HBRelog Server"); CurrentProfileName = HBRelogRemoteApi.GetCurrentProfileName(HbProcId); QBCLog.DeveloperInfo(string.Format("HBRelog Current Profile: {0}", CurrentProfileName)); } else { QBCLog.Error("Could Not Connect to HBRelog Server at net.pipe://localhost/HBRelog/Server"); } } catch (Exception ex) { QBCLog.Error( "Could not make endpoint connection to HBRelog Application. You may not be running under HBRelog. Ignoring"); CurrentProfileName = string.Empty; } } }
private T UtilTo <T>(string attributeName, string attributeValueAsString) { Type concreteType = typeof(T); // Booleans require special handling... if (concreteType == typeof(bool)) { int tmpInt; if (int.TryParse(attributeValueAsString, NumberStyles.Integer, CultureInfo.InvariantCulture, out tmpInt)) { attributeValueAsString = (tmpInt != 0) ? "true" : "false"; QBCLog.Warning(QBCLog.BuildMessageWithContext(Element, "Attribute's '{1}' value was provided as an integer (saw '{2}')--a boolean was expected.{0}" + "The integral value '{2}' was converted to Boolean({3}).{0}" + "Please update to provide '{3}' for this value.", Environment.NewLine, attributeName, tmpInt, attributeValueAsString)); } // Fall through for normal boolean conversion } // Enums require special handling... else if (concreteType.IsEnum) { T tmpValue = default(T); try { tmpValue = (T)Enum.Parse(concreteType, attributeValueAsString); if (!Enum.IsDefined(concreteType, tmpValue)) { throw new ArgumentException(); } // If the provided value is a number instead of Enum name, ask the profile writer to fix it... // This is not fatal, so we let it go without flagging IsAttributeProblem. int tmpInt; if (int.TryParse(attributeValueAsString, NumberStyles.Integer, CultureInfo.InvariantCulture, out tmpInt)) { QBCLog.Warning(QBCLog.BuildMessageWithContext(Element, "The '{1}' attribute's value '{2}' has been implicitly converted" + " to the corresponding enumeration '{3}'.{0}" + "Please use the enumeration name '{3}' instead of a number.", Environment.NewLine, attributeName, tmpInt, tmpValue.ToString())); } } catch (Exception) { QBCLog.Error(QBCLog.BuildMessageWithContext(Element, "The value '{1}' is not a member of the {2} enumeration." + " Allowed values: {3}", Environment.NewLine, attributeValueAsString, concreteType.Name, string.Join(", ", Enum.GetNames(concreteType)))); throw; } return(tmpValue); } try { return((T)Convert.ChangeType(attributeValueAsString, concreteType, CultureInfo.InvariantCulture)); } catch (Exception except) { QBCLog.Error(QBCLog.BuildMessageWithContext(Element, "The '{1}' attribute's value (saw '{2}') is malformed. ({3})", Environment.NewLine, attributeName, attributeValueAsString, except.GetType().Name)); throw; } }
public ButtonPressOnAura(Dictionary <string, string> args) : base(args) { QBCLog.BehaviorLoggingContext = this; try { int[] tmpAuras; // FOR FUTURE IMPLEMENTATION... // Self Auras -- //for (int i = 1; i <= 12; ++i) //{ // string attributeName = string.Format("Button{0}SelfAuraId", i); // tmpAuras = GetNumberedAttributesAsIntegerArray(attributeName, 0, 1, int.MaxValue, null) ?? new int[0]; // UtilPopulateMapWithAuras(SelfAuraToButtonMap, i, tmpAuras); //} // Target Auras -- for (int i = 1; i <= 12; ++i) { string attributeName = string.Format("Button{0}TargetAuraId", i); tmpAuras = GetNumberedAttributesAsArray <int>(attributeName, 0, ConstrainAs.AuraId, null); UtilPopulateMapWithAuras(_targetAuraToButtonMap, i, tmpAuras); } ButtonOnQuestComplete = GetAttributeAsNullable <int>("ButtonOnQuestComplete", false, ConstrainAs.HotbarButton, null); HuntingGroundAnchor = GetAttributeAsNullable <WoWPoint>("", false, ConstrainAs.WoWPointNonEmpty, null) ?? Me.Location; HuntingGroundRadius = GetAttributeAsNullable <double>("HuntingGroundRadius", false, new ConstrainTo.Domain <double>(1.0, 200.0), null) ?? 120.0; IgnoreMobsInBlackspots = GetAttributeAsNullable <bool>("IgnoreMobsInBlackspots", false, null, null) ?? false; MobIds = GetNumberedAttributesAsArray <int>("MobId", 1, ConstrainAs.MobId, null); NonCompeteDistance = GetAttributeAsNullable <double>("NonCompeteDistance", false, new ConstrainTo.Domain <double>(1.0, 150.0), null) ?? 25.0; PostInteractDelay = TimeSpan.FromMilliseconds(GetAttributeAsNullable <int>("PostInteractDelay", false, new ConstrainTo.Domain <int>(0, 61000), null) ?? 1000); QuestId = GetAttributeAsNullable <int>("QuestId", true, ConstrainAs.QuestId(this), null) ?? 0; QuestRequirementComplete = GetAttributeAsNullable <QuestCompleteRequirement>("QuestCompleteRequirement", false, null, null) ?? QuestCompleteRequirement.NotComplete; QuestRequirementInLog = GetAttributeAsNullable <QuestInLogRequirement>("QuestInLogRequirement", false, null, null) ?? QuestInLogRequirement.InLog; // Semantic coherency -- if ((_selfAuraToButtonMap.Count() == 0) && (_targetAuraToButtonMap.Count() == 0)) { QBCLog.Error("You must specify at least one ButtonNTargetAura attribute."); IsAttributeProblem = true; } // Final initialization... _behavior_HuntingGround = new HuntingGroundBehavior(ViableTargets, HuntingGroundAnchor, HuntingGroundRadius); } 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; } }
protected override Composite CreateMainBehavior() { return(_root ?? (_root = new PrioritySelector( // don't drop down while wait timer is running new Decorator(ctx => !_waitTimer.IsFinished, new ActionAlwaysSucceed()), new Decorator(ret => Counter > NumOfTimes, new Action(ret => BehaviorDone(string.Format("Used the item {0} times", NumOfTimes)))), // If item is not in our backpack, behavior is done... new Decorator(context => Item == null, new Action(context => { QBCLog.Error("ItemId({0}) is not in our backpack", ItemId); TreeRoot.Stop(); BehaviorDone("Item is not in our backpack"); })), // Wait for item to come off of cooldown... new Decorator(context => Item.CooldownTimeLeft > TimeSpan.Zero, new Action(context => QBCLog.Info("Waiting for {0} to leave cooldown (time remaining: {1})", Item.SafeName, Item.CooldownTimeLeft))), new Decorator( ret => UseType == QBType.PointToPoint, new PrioritySelector( new Decorator( ret => Me.Location.Distance(MoveToLocation) > 3, new ActionRunCoroutine(context => UtilityCoroutine.MoveTo(MoveToLocation, "Destination", MovementBy))), new Sequence( new Action(ret => TreeRoot.StatusText = string.Format("Using Quest Item: {0} Out of {1} Times", Counter, NumOfTimes)), new Action(ret => Navigator.PlayerMover.MoveStop()), new Action(ret => Me.SetFacing(ClickToLocation)), new SleepForLagDuration(), new Action(ret => Item.UseContainerItem()), new SleepForLagDuration(), new Action(ret => Counter++), new Action(ret => SpellManager.ClickRemoteLocation(ClickToLocation)), new Action(ctx => _waitTimer.Reset()) ))), new Decorator( ret => UseType == QBType.PointToObject, new PrioritySelector( new Decorator( ret => UseObject == null && Me.Location.DistanceSqr(MoveToLocation) >= 2 * 2, new Sequence( new Action(ret => TreeRoot.StatusText = "Moving to location"), new ActionRunCoroutine(context => UtilityCoroutine.MoveTo(MoveToLocation, "Destination", MovementBy)))), new Decorator( ret => UseObject != null, new PrioritySelector( new Decorator( ret => UseObject.DistanceSqr >= Range * Range, new Sequence( new Action(ret => TreeRoot.StatusText = "Moving closer to the object"), new ActionRunCoroutine(context => UtilityCoroutine.MoveTo(UseObject.Location, "UseObject location", MovementBy)))), new Decorator( ret => UseObject.DistanceSqr < MinRange * MinRange, new Sequence( new Action(ret => TreeRoot.StatusText = "Too Close, Backing Up"), new ActionRunCoroutine(context => UtilityCoroutine.MoveTo( WoWMathHelper.CalculatePointFrom(Me.Location, UseObject.Location, (float)MinRange + 2f), "Backing up", MovementBy)) )), new Sequence( new Action(ret => TreeRoot.StatusText = string.Format("Using Item: {0} {1} Out of {2} Times", UseObject.SafeName, Counter, NumOfTimes)), new Action(ret => Navigator.PlayerMover.MoveStop()), new Action(ret => Me.SetFacing(UseObject.Location)), new SleepForLagDuration(), new Action(ret => Item.UseContainerItem()), new Action(ret => Counter++), new SleepForLagDuration(), new Action(ret => SpellManager.ClickRemoteLocation(UseObject.Location)), new Action(ret => _npcBlacklist.Add(UseObject.Guid)), new Action(ctx => _waitTimer.Reset())))), new Action(ret => TreeRoot.StatusText = "No objects around. Waiting") )), new Decorator( ret => UseType == QBType.ToObject, new PrioritySelector( new Decorator( ret => UseObject != null, new PrioritySelector( new Decorator( ret => UseObject.DistanceSqr >= Range * Range, new Sequence( new Action(ret => TreeRoot.StatusText = "Moving to object's range"), new ActionRunCoroutine(context => UtilityCoroutine.MoveTo(UseObject.Location, "UseObject location", MovementBy)))), new Decorator( ret => UseObject.DistanceSqr < MinRange * MinRange, new Sequence( new Action(ret => TreeRoot.StatusText = "Too Close, Backing Up"), new ActionRunCoroutine( context => UtilityCoroutine.MoveTo( WoWMathHelper.CalculatePointFrom(Me.Location, UseObject.Location, (float)MinRange + 2f), "Backing up", MovementBy)) )), new Sequence( new Action(ret => TreeRoot.StatusText = string.Format("Using Item: {0} {1} Out of {2} Times", UseObject.SafeName, Counter, NumOfTimes)), new Action(ret => Navigator.PlayerMover.MoveStop()), new Action(ret => Me.SetFacing(UseObject.Location)), new SleepForLagDuration(), new Action(ret => Item.UseContainerItem()), new Action(ret => Counter++), new SleepForLagDuration(), new Action(ret => SpellManager.ClickRemoteLocation(UseObject.Location)), new Action(ret => _npcBlacklist.Add(UseObject.Guid)), new Action(ctx => _waitTimer.Reset())))), new Decorator( ret => Me.Location.DistanceSqr(MoveToLocation) > 2 * 2, new Sequence( new Action(ret => TreeRoot.StatusText = "Moving to location"), new ActionRunCoroutine(context => UtilityCoroutine.MoveTo(MoveToLocation, "Destination", MovementBy)))) )) ))); }
protected override Composite CreateBehavior() { return(_Root ?? (_Root = new PrioritySelector(context => !s_isBehaviorDone, #region MyHotSpot // Store our current location. new Decorator(context => MyHotSpot == WoWPoint.Empty, new Sequence( new DecoratorContinue(context => Me.IsMoving, new WaitContinue(TimeSpan.FromMilliseconds(2000), context => false, new ActionAlwaysSucceed()) ), new DecoratorContinue(context => !Me.IsMoving, new Action(context => MyHotSpot = Me.Location) ) ) ), #endregion #region MinLevel // Should we check for partymember minumum level ? new Decorator(context => (MinLevel > 0), new Sequence( // Someone is below MinLevel. new DecoratorContinue(context => !CheckLevel(), new Sequence( new Action(context => QBCLog.Info("Someone in your party is below level {0}.", MinLevel)), new Action(context => s_isBehaviorDone = true) ) ), // Everyone is equal or above MinLevel. new DecoratorContinue(context => CheckLevel(), new Action(context => MinLevel = 0) ) ) ), #endregion #region CheckRange // Should we wait for party members to be in range ? new Decorator(context => (CheckRange != 0), new Sequence( // Everyone isn't within interact range, lets wait abit before checking again. new DecoratorContinue(context => !CheckPartyRange(), new Sequence( new DecoratorContinue(context => !Navigator.AtLocation(MyHotSpot), new Sequence( new DecoratorContinue(context => Navigator.CanNavigateFully(Me.Location, MyHotSpot), new Action(context => Navigator.MoveTo(MyHotSpot)) ), new DecoratorContinue(context => !Navigator.CanNavigateFully(Me.Location, MyHotSpot), new Action(context => Flightor.MoveTo(MyHotSpot)) ) ) ), new WaitContinue(TimeSpan.FromMilliseconds(300), context => false, new ActionAlwaysSucceed()) ) ), // Everyone is within interact range. new DecoratorContinue(context => CheckPartyRange(), new Sequence( new Action(context => QBCLog.Info("Everyone is within range.")), new Action(context => CheckRange = 0) ) ) ) ), #endregion #region ChkExp // Disabled until I can find out a safer way to to it. /* * new Decorator(context => (ChkExp != 0), * new Sequence( * new DecoratorContinue(context => !AreWeDone(), * new Action(context => CheckExpansions()) * ), * new DecoratorContinue(context => AreWeDone(), * new Sequence( * new DecoratorContinue(context => !DoAllHaveExp(), * new Sequence( * new Action(context => QBCLog.Info("Everyone in your group doesn't have ExpansionLevel '{0}'", ChkExp)), * new Action(context => _isBehaviorDone = true) * ) * ), * new DecoratorContinue(context => DoAllHaveExp(), * new Sequence( * new Action(context => QBCLog.Info("Everyone has atleast ExpansionLevel '{0}'", ChkExp)), * new Action(context => ChkExp = 0) * ) * ) * ) * ) * ) * ), */ #endregion #region RemotePath // Load the remote profile... new Decorator(context => RemotePath != "", new Sequence( // You have included a RemotePath but not a ProfileName. new DecoratorContinue(context => ProfileName == "", new Sequence( new Action(context => QBCLog.Error("You need to include a ProfileName.")), new Action(context => s_isBehaviorDone = true) ) ), // Remote Profile doesn't exist. new DecoratorContinue(context => (ProfileName != "" && !UrlExists(NewRemoteProfilePath)), new Sequence( new Action(context => QBCLog.Error("Profile '{0}' does not exist.", ProfileName)), new Action(context => s_isBehaviorDone = true) ) ), // Everything is ok, Load the remote Profile new DecoratorContinue(context => (ProfileName != "" && UrlExists(NewRemoteProfilePath)), new Sequence( new Action(context => TreeRoot.StatusText = "Loading profile '" + ProfileName + "'"), new Action(context => QBCLog.Info("Loading profile '{0}'", ProfileName)), new Action(context => ProfileManager.LoadNew(new MemoryStream(new WebClient().DownloadData(NewRemoteProfilePath)))), new WaitContinue(TimeSpan.FromMilliseconds(300), context => false, new ActionAlwaysSucceed()), new Action(context => s_isBehaviorDone = true) ) ) ) ), #endregion #region ProfileName // Load the local profile... new Decorator(context => (ProfileName != "" && RemotePath == ""), new PrioritySelector( // Local Profile doesn't exist. new Decorator(context => !IsStoreProfile && !File.Exists(NewLocalProfilePath), new Sequence( new Action(context => QBCLog.Error("Profile '{0}' does not exist.", ProfileName)), new Action(context => s_isBehaviorDone = true) ) ), // Everything is ok, Load the local Profile. new Sequence( new Action(context => TreeRoot.StatusText = "Loading profile '" + ProfileName + "'"), new Action(context => QBCLog.Error("Loading profile '{0}'", ProfileName)), new Action(context => ProfileManager.LoadNew(NewLocalProfilePath, false)), new WaitContinue(TimeSpan.FromMilliseconds(300), context => false, new ActionAlwaysSucceed()), new Action(context => s_isBehaviorDone = true) ) ) ), #endregion #region Behavior Done // Everyone is within interact range and we shouldn't load a profile, then end the Quest Behavior. new Decorator(context => !s_isBehaviorDone, new Action(context => s_isBehaviorDone = true) ) #endregion ) )); }
private string UtilLocateKey(bool isAttributeRequired, string primaryName, string[] aliasNames) { // Register keys as recognized UtilRecognizeAttributeNames(primaryName, aliasNames); // Make sure the key was only specified once -- // The 'dictionary' nature of Args assures that a key name will only be in the dictionary once. // However, if the key has been renamed, and an alias maintained for backward-compatibility, // then the user could specify the primary key name and one or more aliases as attributes. // If all the aliases provided the same value, then it is harmless, but we don't make the // distinction. Instead, we encourage the user to use the preferred name of the key. This // eliminates any possibility of the user specifying conflicting values for the 'same' attribute. if (UtilCountKeyNames(primaryName, aliasNames) > 1) { var keyNames = new List <string> { primaryName }; keyNames.AddRange(aliasNames); keyNames.Sort(); QBCLog.Error(QBCLog.BuildMessageWithContext(Element, "The attributes [{1}] are aliases for each other, and thus mutually exclusive.{0}" + "Please specify the attribute by its preferred name '{2}'.", Environment.NewLine, ("'" + string.Join("', '", keyNames.ToArray()) + "'"), primaryName)); IsAttributeProblem = true; return(null); } // Prefer the primary name... if (!string.IsNullOrEmpty(primaryName) && Attributes.ContainsKey(primaryName)) { return(primaryName); } if (aliasNames != null) { string keyName = (from aliasName in aliasNames where !string.IsNullOrEmpty(aliasName) && Attributes.ContainsKey(aliasName) select aliasName).FirstOrDefault(); if (!string.IsNullOrEmpty(keyName)) { QBCLog.Warning(QBCLog.BuildMessageWithContext(Element, "Found attribute via its alias name '{1}'.{0}" + "Please update to use its primary name '{2}', instead.", Environment.NewLine, keyName, primaryName)); return(keyName); } } // Attribute is required, but cannot be located... if (isAttributeRequired) { QBCLog.Error(QBCLog.BuildMessageWithContext(Element, "Attribute '{1}' is required, but was not provided.", Environment.NewLine, primaryName)); IsAttributeProblem = true; } return(null); }