public static void ShowVehicleArticulationChain(WoWUnit wowUnit) { var tmp = new StringBuilder(); var indentLevel = 4; do { var indent = string.Empty.PadLeft(indentLevel); var fieldSeparator = string.Format("\n {0}", indent); tmp.Append(wowUnit.SafeName); var worldMatrix = wowUnit.GetWorldMatrix(); var pitch = StyxWoW.Memory.Read <float>(wowUnit.BaseAddress + 0x820 + 0x24); tmp.AppendFormat("{0}{1} (pitch: {2}): {3}", fieldSeparator, wowUnit.SafeName, pitch, worldMatrix.ToString_FullInfo(false, indentLevel)); wowUnit = wowUnit.Transport as WoWUnit; if (wowUnit != null) { tmp.AppendFormat("{0} => ", fieldSeparator); } indentLevel += 4; } while (wowUnit != null); QBCLog.Debug("Articulation chain: {0}", tmp.ToString()); }
/// <summary> /// Executes a hook. This also sets QBCLog.BehaviorLoggingContext and logs when hook starts/stops executing, if enabled /// </summary> /// <param name="cb">The CustomForcedBehavior.</param> /// <param name="taskProducer">The task producer.</param> /// <param name="name">The name. Used to identify hooks that can have multiple instances running at a time.</param> /// <param name="logExecution">if set to <c>true</c> [log execution].</param> /// <returns> /// Returns value produced by the coroutine returned from <paramref name="taskProducer" />. /// </returns> /// <exception cref="Exception">Coroutine status was invalid</exception> /// <exception cref="System.Exception">Coroutine status was invalid</exception> public static async Task <bool> ExecuteHook(CustomForcedBehavior cb, Func <Task <bool> > taskProducer, string name = "", bool logExecution = true) { using (var coroutine = new Coroutine(async() => await taskProducer())) { var hookType = cb.GetType(); string identifier = hookType + name; // Change the logging context to the Hook instance so QBCLog messages correctly display the originating QB. var originalLoggingContext = QBCLog.BehaviorLoggingContext; QBCLog.BehaviorLoggingContext = cb; try { while (true) { coroutine.Resume(); bool executed; switch (coroutine.Status) { case CoroutineStatus.Runnable: executed = true; break; case CoroutineStatus.RanToCompletion: executed = (bool)coroutine.Result; break; default: throw new Exception("Unexpected Coroutine status"); } if (logExecution) { bool executedPreviously; s_hookExecutionStates.TryGetValue(identifier, out executedPreviously); if (executed != executedPreviously) { s_hookExecutionStates[identifier] = executed; // log execution state changes. QBCLog.Debug(executed ? "Executing {0}hook" : "Stopped executing {0}hook", name != null ? name + " " : ""); } } if (coroutine.Status != CoroutineStatus.Runnable) { return(executed); } await Coroutine.Yield(); } } finally { QBCLog.BehaviorLoggingContext = originalLoggingContext; } } }
// Stolen from Singluar. private static WoWGuid ArgToGuid(object o) { string svalue = o.ToString(); try { WoWGuid guid; if (WoWGuid.TryParseFriendly(svalue, out guid)) { return(guid); } } catch { QBCLog.Debug("error parsing Guid '{0}'", o.ToString()); } return(WoWGuid.Empty); }
/// <summary> /// <para>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.</para> /// <para>It also captures the user's configuration, and installs Behavior Tree hooks. The items will /// be restored when the behavior terminates, or Honorbuddy is stopped.</para> /// </summary> /// <return>true, if the behavior should run; false, if it should not.</return> /// <param name="extraGoalTextDescription"></param> protected bool OnStart_QuestBehaviorCore(string extraGoalTextDescription = null) { // Semantic coherency / covariant dependency checks... UsageCheck_SemanticCoherency(Element, QuestObjectiveIndex > 0 && !VariantQuestIds.Any(), context => $"QuestObjectiveIndex of '{QuestObjectiveIndex}' specified, but no corresponding QuestId provided"); UsageCheck_SemanticCoherency(Element, _providedQuestIdAndQuestVariantIds, context => "Cannot provide both a QuestId and VariantQuestIds at same time."); EvaluateUsage_SemanticCoherency(Element); // Deprecated attributes... EvaluateUsage_DeprecatedAttributes(Element); // 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(); var questId = GetQuestId(); // 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. // NB: Since the IsDone property may skip checking the 'progress conditions', we need to explicltly // check them here to see if we even need to start the behavior. if (!(IsDone || !UtilIsProgressRequirementsMet(questId, QuestRequirementInLog, QuestRequirementComplete))) { this.UpdateGoalText(questId, extraGoalTextDescription); // Start the timer to measure the behavior run time... _behaviorRunTimer.Restart(); // Monitored Behaviors... if (QuestBehaviorCoreSettings.Instance.MonitoredBehaviors.Contains(GetType().Name)) { QBCLog.Debug("MONITORED BEHAVIOR: {0}", GetType().Name); AudibleNotifyOn(true); } _configMemento = CreateConfigMemento(); if (Targeting.Instance != null) { Targeting.Instance.IncludeTargetsFilter += TargetFilter_IncludeTargets; Targeting.Instance.RemoveTargetsFilter += TargetFilter_RemoveTargets; Targeting.Instance.WeighTargetsFilter += TargetFilter_WeighTargets; } Query.InCompetitionReset(); Utility.BlacklistsReset(); _behaviorTreeHook_CombatMain = BehaviorHookInstall("Combat_Main", CreateBehavior_CombatMain()); _behaviorTreeHook_CombatOnly = BehaviorHookInstall("Combat_Only", CreateBehavior_CombatOnly()); _behaviorTreeHook_DeathMain = BehaviorHookInstall("Death_Main", CreateBehavior_DeathMain()); _behaviorTreeHook_QuestbotMain = BehaviorHookInstall("Questbot_Main", CreateBehavior_QuestbotMain()); BlackspotManager.AddBlackspots(_temporaryBlackspots.GetBlackspots()); if (_temporaryAvoidMobs != null) { foreach (var avoidMobId in _temporaryAvoidMobs.GetAvoidMobIds()) { // NB: ProfileManager.CurrentProfile.AvoidMobs will never be null if (!ProfileManager.CurrentProfile.AvoidMobs.Contains(avoidMobId)) { ProfileManager.CurrentProfile.AvoidMobs.Add(avoidMobId); } } } return(true); // behavior should run } return(false); // behavior should NOT run }