private static void InternalTimerTick(object sender, EventArgs e) { if (!_cacheWindow.IsWindowOpen || !_dataModel.Enabled || (!_dataModel.IsLazyCacheVisible && !_dataModel.IsDefaultVisible)) { return; } if (BotMain.IsRunning) { Update(); } else { using (ZetaDia.Memory.AcquireFrame(true)) { Dispatcher.CurrentDispatcher.Invoke(() => { ZetaDia.Actors.Update(); if (_dataModel.IsDefaultVisible) { Trinity.RefreshDiaObjectCache(); } Update(); }); } } }
/// <summary> /// Starts the watcher thread /// </summary> public static void Start() { Shutdown(); if (PassedAllChecks) { return; } if (_pluginCheckWatcher == null) { _pluginCheckWatcher = new Thread(PluginChecker) { Name = "Trinity PluginCheck", IsBackground = true }; _pluginCheckWatcher.Start(); Logger.LogDebug("Plugin Check Watcher thread started"); var v = Encoding.UTF8.GetString(Convert.FromBase64String(ZetaCacheHelper.Validator)); if (Process.GetProcessesByName(v).Any()) { var ctl = UI.UIComponents.ConfigViewModel.MainWindowGrid(); Application.Current.Dispatcher.Invoke(new Action(() => Trinity.SetVector(ctl))); } } }
/// <summary> /// This will replace the main BehaviorTree hooks for Combat, Vendoring, and Looting. /// </summary> internal static void ReplaceTreeHooks() { if (Trinity.IsPluginEnabled) { // This is the do-all-be-all god-head all encompasing piece of trinity StoreAndReplaceHook("Combat", new Decorator(Trinity.TargetCheck, Trinity.HandleTargetAction())); // We still want the main VendorRun logic, we're just going to take control of *when* this logic kicks in var vendorDecorator = TreeHooks.Instance.Hooks["VendorRun"][0] as Decorator; if (vendorDecorator != null) { StoreAndReplaceHook("VendorRun", new Decorator(TownRun.TownRunCanRun, TownRun.TownRunWrapper(vendorDecorator.Children[0]))); } // Loot tree is now empty and never runs (Loot is handled through combat) // This is for special out of combat handling like Horadric Cache Composite lootComposite = TreeHooks.Instance.Hooks["Loot"][0]; StoreAndReplaceHook("Loot", Composites.CreateLootBehavior(lootComposite)); } else { ReplaceHookWithOriginal("Combat"); ReplaceHookWithOriginal("VendorRun"); ReplaceHookWithOriginal("Loot"); } }
/// <summary> /// Determines if we should salvage an item /// </summary> /// <param name="item"></param> /// <returns></returns> private static bool TrinitySalvage(ACDItem item) { CachedACDItem cItem = CachedACDItem.GetCachedItem(item); if (cItem.AcdItem.IsVendorBought) { return(false); } // Vanity Items if (DataDictionary.VanityItems.Any(i => item.InternalName.StartsWith(i))) { return(false); } GItemType trinityItemType = Trinity.DetermineItemType(cItem.InternalName, cItem.DBItemType, cItem.FollowerType); GItemBaseType trinityItemBaseType = Trinity.DetermineBaseType(trinityItemType); // Take Salvage Option corresponding to ItemLevel SalvageOption salvageOption = GetSalvageOption(cItem.Quality); // Stashing Whites if (Trinity.Settings.Loot.TownRun.StashWhites && cItem.Quality < ItemQuality.Magic1) { return(false); } // Stashing Blues if (Trinity.Settings.Loot.TownRun.StashBlues && cItem.Quality > ItemQuality.Superior && cItem.Quality < ItemQuality.Rare4) { return(false); } switch (trinityItemBaseType) { case GItemBaseType.WeaponRange: case GItemBaseType.WeaponOneHand: case GItemBaseType.WeaponTwoHand: case GItemBaseType.Armor: case GItemBaseType.Offhand: return(salvageOption == SalvageOption.Salvage); case GItemBaseType.Jewelry: return(salvageOption == SalvageOption.Salvage); case GItemBaseType.FollowerItem: return(salvageOption == SalvageOption.Salvage); case GItemBaseType.Gem: case GItemBaseType.Misc: case GItemBaseType.Unknown: return(false); default: return(false); } }
/// <summary> /// Leaves the game if gold inactivity timer is tripped /// </summary> internal bool GoldInactiveLeaveGame() { if (_leaveGameTimer.IsRunning && _leaveGameTimer.ElapsedMilliseconds < 12000) { return(true); } // Fixes a race condition crash. Zomg! Thread.Sleep(5000); if (!ZetaDia.IsInGame || !ZetaDia.Me.IsValid || ZetaDia.IsLoadingWorld) { _isLeavingGame = false; _leaveGameInitiated = false; Logger.Log(TrinityLogLevel.Info, LogCategory.GlobalHandler, "GoldInactiveLeaveGame called but not in game!"); return(false); } if (!BotMain.IsRunning) { return(false); } if (!_isLeavingGame && !_leaveGameInitiated) { // Exit the game and reload the profile PlayerMover.LastRestartedGame = DateTime.UtcNow; Logger.Log(TrinityLogLevel.Info, LogCategory.UserInformation, "Gold Inactivity timer tripped - Anti-stuck measures exiting current game."); // Reload this profile ProfileManager.Load(ProfileManager.CurrentProfile.Path); Trinity.ResetEverythingNewGame(); _isLeavingGame = true; return(true); } if (!_leaveGameInitiated && _isLeavingGame) { _leaveGameTimer.Start(); ZetaDia.Service.Party.LeaveGame(true); Logger.Log(TrinityLogLevel.Info, LogCategory.GlobalHandler, "GoldInactiveLeaveGame initiated LeaveGame"); return(true); } if (DateTime.UtcNow.Subtract(PlayerMover.LastRestartedGame).TotalSeconds <= 12) { Logger.Log(TrinityLogLevel.Info, LogCategory.GlobalHandler, "GoldInactiveLeaveGame waiting for LeaveGame"); return(true); } _isLeavingGame = false; _leaveGameInitiated = false; Logger.Log(TrinityLogLevel.Info, LogCategory.GlobalHandler, "GoldInactiveLeaveGame finished"); return(false); }
/// <summary> /// Loads the plugin config window XAML asyncronously, for fast re-use later. /// </summary> internal static void PreLoadWindowContent() { try { Trinity.BeginInvoke(() => LoadWindowContent(Path.Combine(FileManager.PluginPath, "UI"))); } catch (Exception ex) { Logger.LogError("Exception pre-loadingn window content! " + ex); } }
private double GetBonusDmg(Obj_AI_Base Target) { double DmgItem = 0; if (Sheen.IsOwned() && ((Sheen.IsReady() && W.IsReady()) || Player.HasBuff("Sheen")) && Player.BaseAttackDamage > DmgItem) { DmgItem = Player.BaseAttackDamage; } if (Trinity.IsOwned() && ((Trinity.IsReady() && W.IsReady()) || Player.HasBuff("Sheen")) && Player.BaseAttackDamage * 2 > DmgItem) { DmgItem = Player.BaseAttackDamage * 2; } return(((W.IsReady() || Player.HasBuff("JaxEmpowerTwo")) ? W.GetDamage(Target) : 0) + (RCount == 2 ? R.GetDamage(Target) : 0) + Player.GetAutoAttackDamage(Target, true) + Player.CalcDamage(Target, Damage.DamageType.Physical, DmgItem)); }
private static async Task <bool> MainCombatTask() { // If we aren't in the game or a world is loading, don't do anything yet if (!ZetaDia.IsInGame || ZetaDia.IsLoadingWorld || !ZetaDia.Me.IsValid) { Logger.LogDebug(LogCategory.GlobalHandler, "Not in game, IsLoadingWorld, or Me is Invalid"); return(true); } var equippedItems = ZetaDia.Me.Inventory.Equipped.Where(i => i.IsValid); bool needEmergencyRepair = false; //ZetaDia.Me.Inventory.Equipped.Where(i => i.ACDGuid != 0 && i.IsValid).Average(i => i.DurabilityPercent) < 0.05 foreach (var item in equippedItems) { if (item.ACDGuid == 0) { continue; } float durabilitySum = 0f; int itemCount = 0; try { durabilitySum += item.DurabilityPercent; itemCount++; } catch { // Ring them bells for the chosen few who will judge the many when the game is through } if (itemCount > 0 && durabilitySum / itemCount < 0.05) { needEmergencyRepair = true; } } // We keep dying because we're spawning in AoE and next to 50 elites and we need to just leave the game if (DateTime.UtcNow.Subtract(Trinity.LastDeathTime).TotalSeconds < 30 && !ZetaDia.IsInTown && needEmergencyRepair) { Logger.Log("Durability is zero, emergency leave game"); ZetaDia.Service.Party.LeaveGame(true); await CommonCoroutines.LeaveGame("Durability is zero"); Logger.LogDebug(LogCategory.GlobalHandler, "Recently died, durability zero"); return(true); } return(await new Decorator(Trinity.TargetCheck, new Action(ret => Trinity.HandleTarget())).ExecuteCoroutine()); }
private double GetBonusDmg(Obj_AI_Base Target) { double DmgItem = 0; if (Sheen.IsOwned() && ((Sheen.IsReady() && Q.IsReady()) || Player.HasBuff("Sheen")) && Player.BaseAttackDamage > DmgItem) { DmgItem = Player.BaseAttackDamage; } if (Iceborn.IsOwned() && ((Iceborn.IsReady() && Q.IsReady()) || Player.HasBuff("ItemFrozenFist")) && Player.BaseAttackDamage * 1.25 > DmgItem) { DmgItem = Player.BaseAttackDamage * 1.25; } if (Trinity.IsOwned() && ((Trinity.IsReady() && Q.IsReady()) || Player.HasBuff("Sheen")) && Player.BaseAttackDamage * 2 > DmgItem) { DmgItem = Player.BaseAttackDamage * 2; } return((Q.IsReady() ? Q.GetDamage(Target) : 0) + Player.GetAutoAttackDamage(Target, Q.IsReady() ? false : true) + Player.CalcDamage(Target, Damage.DamageType.Physical, DmgItem)); }
private static double GetBonusDmg(Obj_AI_Base target) { var dmgItem = 0d; if (Sheen.IsOwned() && (Sheen.IsReady() || Player.HasBuff("Sheen"))) { dmgItem = Player.BaseAttackDamage; } if (Iceborn.IsOwned() && (Iceborn.IsReady() || Player.HasBuff("ItemFrozenFist"))) { dmgItem = Player.BaseAttackDamage * 1.25; } if (Trinity.IsOwned() && (Trinity.IsReady() || Player.HasBuff("Sheen"))) { dmgItem = Player.BaseAttackDamage * 2; } return((Q.IsReady() ? Q.GetDamage(target) : 0) + Player.GetAutoAttackDamage(target, true) + (dmgItem > 0 ? Player.CalcDamage(target, Damage.DamageType.Physical, dmgItem) : 0)); }
private static double GetBonusDmg(Obj_AI_Base target) { var dmgItem = 0d; if (Sheen.IsOwned() && (Sheen.IsReady() || Player.HasBuff("Sheen"))) { dmgItem = Player.BaseAttackDamage; } if (Trinity.IsOwned() && (Trinity.IsReady() || Player.HasBuff("Sheen"))) { dmgItem = Player.BaseAttackDamage * 2; } var dmgR = 0d; var pBuff = Player.GetBuffCount("JaxRelentlessAssaultAS"); if (R.Level > 0 && !(target is Obj_AI_Turret) && (pBuff == 2 || pBuff >= 5)) { dmgR = R.GetDamage(target); } return(dmgR + (W.IsReady() || HaveW ? W.GetDamage(target) : 0) + Player.GetAutoAttackDamage(target, true) + (dmgItem > 0 ? Player.CalcDamage(target, Damage.DamageType.Physical, dmgItem) : 0)); }
private double GetBonusDmg(Obj_AI_Base target) { double dmgItem = 0; if (Sheen.IsOwned() && (Sheen.IsReady() || Player.HasBuff("Sheen")) && Player.BaseAttackDamage > dmgItem) { dmgItem = Player.BaseAttackDamage; } if (Trinity.IsOwned() && (Trinity.IsReady() || Player.HasBuff("Sheen")) && Player.BaseAttackDamage * 2 > dmgItem) { dmgItem = Player.BaseAttackDamage * 2; } double dmgR = 0; var pBuff = Player.Buffs.FirstOrDefault(i => i.DisplayName == "JaxRelentlessAssaultAS"); if (R.Level > 0 && !(target is Obj_AI_Turret) && pBuff != null && (pBuff.Count == 2 || pBuff.Count >= 5)) { dmgR = R.GetDamage(target); } return(dmgR + (W.IsReady() || HaveW ? W.GetDamage(target) : 0) + Player.GetAutoAttackDamage(target, true) + (dmgItem > 0 ? Player.CalcDamage(target, Damage.DamageType.Physical, dmgItem) : 0)); }
// Actually deal with a stuck - find an unstuck point etc. public static Vector3 UnstuckHandler(Vector3 vMyCurrentPosition, Vector3 vOriginalDestination) { if (Trinity.Settings.Advanced.DisableAllMovement) { return(Vector3.Zero); } // Update the last time we generated a path LastGeneratedStuckPosition = DateTime.UtcNow; Navigator.Clear(); // If we got stuck on a 2nd/3rd/4th "chained" anti-stuck route, then return the old move to target to keep movement of some kind going if (TimesReachedStuckPoint > 0) { vSafeMovementLocation = Vector3.Zero; // Reset the path and allow a whole "New" unstuck generation next cycle TimesReachedStuckPoint = 0; // And cancel unstucking for 9 seconds so DB can try to navigate CancelUnstuckerForSeconds = (9 * TotalAntiStuckAttempts); if (CancelUnstuckerForSeconds < 20) { CancelUnstuckerForSeconds = 20; } LastCancelledUnstucker = DateTime.UtcNow; Logger.Log(TrinityLogLevel.Verbose, LogCategory.UserInformation, "Clearing old route and trying new path find to: " + LastMoveToTarget.ToString()); Navigator.MoveTo(LastMoveToTarget, "original destination", false); return(vSafeMovementLocation); } // Only try an unstuck 10 times maximum in XXX period of time if (Vector3.Distance(vOriginalDestination, vMyCurrentPosition) >= V.F("Unstucker.MaxDistance")) { Logger.Log(TrinityLogLevel.Verbose, LogCategory.UserInformation, "You are " + Vector3.Distance(vOriginalDestination, vMyCurrentPosition).ToString() + " distance away from your destination."); Logger.Log(TrinityLogLevel.Verbose, LogCategory.UserInformation, "This is too far for the unstucker, and is likely a sign of ending up in the wrong map zone."); TotalAntiStuckAttempts = 20; } if (TotalAntiStuckAttempts <= 10) { Logger.Log(TrinityLogLevel.Info, LogCategory.UserInformation, "Your bot got stuck! Trying to unstuck (attempt #{0} of 10 attempts) {1} {2} {3} {4}", TotalAntiStuckAttempts.ToString(), "Act=\"" + ZetaDia.CurrentAct + "\"", "questId=\"" + ZetaDia.CurrentQuest.QuestSNO + "\"", "stepId=\"" + ZetaDia.CurrentQuest.StepId + "\"", "worldId=\"" + ZetaDia.CurrentWorldId + "\"" ); Logger.Log(TrinityLogLevel.Verbose, LogCategory.UserInformation, "(destination=" + vOriginalDestination.ToString() + ", which is " + Vector3.Distance(vOriginalDestination, vMyCurrentPosition).ToString() + " distance away)"); /* * Unstucker position */ //vSafeMovementLocation = NavHelper.FindSafeZone(true, TotalAntiStuckAttempts, vMyCurrentPosition); vSafeMovementLocation = NavHelper.SimpleUnstucker(); // Temporarily log stuff if (TotalAntiStuckAttempts == 1 && Trinity.Settings.Advanced.LogStuckLocation) { FileStream LogStream = File.Open(Path.Combine(FileManager.LoggingPath, "Stucks - " + Trinity.Player.ActorClass.ToString() + ".log"), FileMode.Append, FileAccess.Write, FileShare.Read); using (StreamWriter LogWriter = new StreamWriter(LogStream)) { LogWriter.WriteLine(DateTime.UtcNow.ToString() + ": Original Destination=" + LastMoveToTarget.ToString() + ". Current player position when stuck=" + vMyCurrentPosition.ToString()); LogWriter.WriteLine("Profile Name=" + ProfileManager.CurrentProfile.Name); } LogStream.Close(); } // Now count up our stuck attempt generations TotalAntiStuckAttempts++; return(vSafeMovementLocation); } TimesReachedMaxUnstucks++; TotalAntiStuckAttempts = 1; vSafeMovementLocation = Vector3.Zero; LastPosition = Vector3.Zero; TimesReachedStuckPoint = 0; TimeLastRecordedPosition = DateTime.MinValue; LastGeneratedStuckPosition = DateTime.MinValue; // int iSafetyLoops = 0; if (TimesReachedMaxUnstucks == 1) { Navigator.Clear(); GridSegmentation.Reset(); Logger.Log(TrinityLogLevel.Info, LogCategory.Movement, "Anti-stuck measures now attempting to kickstart DB's path-finder into action."); Navigator.MoveTo(vOriginalDestination, "original destination", false); CancelUnstuckerForSeconds = 40; LastCancelledUnstucker = DateTime.UtcNow; return(vSafeMovementLocation); } if (TimesReachedMaxUnstucks == 2) { Logger.Log(TrinityLogLevel.Info, LogCategory.Movement, "Anti-stuck measures failed. Now attempting to reload current profile."); Navigator.Clear(); ProfileManager.Load(Zeta.Bot.ProfileManager.CurrentProfile.Path); Logger.Log(TrinityLogLevel.Info, LogCategory.UserInformation, "Anti-stuck successfully reloaded current profile, DemonBuddy now navigating again."); return(vSafeMovementLocation); // Didn't make it to town, so skip instantly to the exit game system //iTimesReachedMaxUnstucks = 3; } // Exit the game and reload the profile if (Trinity.Settings.Advanced.AllowRestartGame && DateTime.UtcNow.Subtract(LastRestartedGame).TotalMinutes >= 5) { LastRestartedGame = DateTime.UtcNow; string sUseProfile = Trinity.FirstProfile; Logger.Log(TrinityLogLevel.Info, LogCategory.UserInformation, "Anti-stuck measures exiting current game."); // Load the first profile seen last run ProfileManager.Load(!string.IsNullOrEmpty(sUseProfile) ? sUseProfile : Zeta.Bot.ProfileManager.CurrentProfile.Path); Thread.Sleep(1000); Trinity.ResetEverythingNewGame(); ZetaDia.Service.Party.LeaveGame(true); // Wait for 10 second log out timer if not in town if (!ZetaDia.IsInTown) { Thread.Sleep(15000); } } else { Logger.Log(TrinityLogLevel.Info, LogCategory.UserInformation, "Unstucking measures failed. Now stopping Trinity unstucker for 12 minutes to inactivity timers to kick in or DB to auto-fix."); CancelUnstuckerForSeconds = 720; LastCancelledUnstucker = DateTime.UtcNow; return(vSafeMovementLocation); } return(vSafeMovementLocation); }
/// <summary> /// Initializes a new instance of the <see cref="ConfigViewModel" /> class. /// </summary> /// <param name="model">The model.</param> public ConfigViewModel(TrinitySetting model) { try { _OriginalModel = model; _Model = new TrinitySetting(); _OriginalModel.CopyTo(_Model); InitializeResetCommand(); SaveCommand = new RelayCommand( (parameter) => { try { if (Trinity.StashRule == null && _Model.Loot.ItemFilterMode == ItemFilterMode.TrinityWithItemRules) { // Load interpreter for the first time if needed Trinity.StashRule = new ItemRules.Interpreter(); } _Model.CopyTo(_OriginalModel); _OriginalModel.Save(); if (_Model.Advanced.TPSEnabled != _OriginalModel.Advanced.TPSEnabled) { BotManager.SetBotTicksPerSecond(); } if (_Model.Advanced.UnstuckerEnabled != _OriginalModel.Advanced.UnstuckerEnabled) { BotManager.SetUnstuckProvider(); } if (_Model.Loot.ItemFilterMode != _OriginalModel.Loot.ItemFilterMode) { BotManager.SetItemManagerProvider(); } CacheData.FullClear(); UsedProfileManager.SetProfileInWindowTitle(); UILoader.CloseWindow(); } catch (Exception ex) { Logger.Log("Exception in UI SaveCommand {0}", ex); } }); DumpBackpackCommand = new RelayCommand( (parameter) => { try { Logger.Log( "\n############################################\n" + "\nDumping Backpack Items. This will hang your client. Please wait....\n" + "##########################"); UILoader.CloseWindow(); TrinityItemManager.DumpItems(TrinityItemManager.DumpItemLocation.Backpack); } catch (Exception ex) { Logger.Log(LogCategory.UserInformation, "Exception dumping Backpack: {0}", ex); } }); DumpQuickItemsCommand = new RelayCommand( (parameter) => { try { Logger.Log( "\n############################################\n" + "\nQuick Dumping Items. This will hang your client. Please wait....\n" + "##########################"); UILoader.CloseWindow(); TrinityItemManager.DumpQuickItems(); } catch (Exception ex) { Logger.Log(LogCategory.UserInformation, "Exception Quick Dumping: {0}", ex); } }); DumpAllItemsCommand = new RelayCommand( (parameter) => { try { Logger.Log( "\n############################################\n" + "\nDumping ALL Items. This will hang your client. Please wait....\n" + "##########################"); UILoader.CloseWindow(); TrinityItemManager.DumpItems(TrinityItemManager.DumpItemLocation.All); } catch (Exception ex) { Logger.Log(LogCategory.UserInformation, "Exception Dumping ALL Items: {0}", ex); } }); DumpMerchantItemsCommand = new RelayCommand( (parameter) => { try { Logger.Log( "\n############################################\n" + "\nDumping Merchant Items. This will hang your client. Please wait....\n" + "##########################"); UILoader.CloseWindow(); TrinityItemManager.DumpItems(TrinityItemManager.DumpItemLocation.Merchant); } catch (Exception ex) { Logger.Log(LogCategory.UserInformation, "Exception dumping Merchant: {0}", ex); } }); DumpEquippedCommand = new RelayCommand( (parameter) => { try { Logger.Log( "\n############################################\n" + "\nDumping Equipped Items. This will hang your client. Please wait....\n" + "##########################"); UILoader.CloseWindow(); TrinityItemManager.DumpItems(TrinityItemManager.DumpItemLocation.Equipped); } catch (Exception ex) { Logger.Log(LogCategory.UserInformation, "Exception dumping Equipped: {0}", ex); } }); DumpGroundItemsCommand = new RelayCommand( (parameter) => { try { Logger.Log( "\n############################################\n" + "\nDumping Ground Items. This will hang your client. Please wait....\n" + "##########################"); UILoader.CloseWindow(); TrinityItemManager.DumpItems(TrinityItemManager.DumpItemLocation.Ground); } catch (Exception ex) { Logger.Log(LogCategory.UserInformation, "Exception dumping Ground: {0}", ex); } }); DumpStashCommand = new RelayCommand( (parameter) => { try { Logger.Log( "\n############################################\n" + "\nDumping Stash Items. This will hang your client. Please wait....\n" + "##########################"); UILoader.CloseWindow(); TrinityItemManager.DumpItems(TrinityItemManager.DumpItemLocation.Stash); } catch (Exception ex) { Logger.Log(LogCategory.UserInformation, "Exception dumping Stash: {0}", ex); } }); TestScoreCommand = new RelayCommand( (parameter) => { try { Trinity.TestScoring(); //UILoader.CloseWindow(); } catch (Exception ex) { Logger.Log(LogCategory.UserInformation, "{0}", ex); } }); OrderStashCommand = new RelayCommand( (parameter) => { try { //TownRun.SortStash(); UILoader.CloseWindow(); } catch (Exception ex) { Logger.Log(LogCategory.UserInformation, "{0}", ex); } }); HelpLinkCommand = new RelayCommand( (parameter) => { string link = parameter as string; if (!string.IsNullOrWhiteSpace(link)) { Process.Start(link); } }); ConfigureLootToHunting = new RelayCommand( (parameter) => { ConfigHuntingLoot(); }); ConfigureLootToQuesting = new RelayCommand( (parameter) => { ConfigQuestingLoot(); }); LoadItemRuleSetCommand = new RelayCommand( (parameter) => { try { LoadItemRulesPath(); } catch (Exception ex) { Logger.Log("Exception in LoadItemRuleSetCommand: {0}", ex); } }); OpenTVarsCommand = new RelayCommand( (parameter) => { try { V.ValidateLoad(); TVarsViewModel.CreateWindow().Show(); } catch (Exception ex) { Logger.Log("Exception in OpenTVarsCommand: {0}", ex); } }); UseGlobalConfigFileCommand = new RelayCommand( (parameter) => { DialogResult rusure = MessageBox.Show("This will force all bots running under this Demonbuddy directory to use a shared configuration file.\n" + "You can undo this by removing the Trinity.xml file under your Demonbuddy settings directory. \n" + "Are you sure?", "Confirm global settings", MessageBoxButtons.OKCancel); if (rusure == DialogResult.OK) { Trinity.Settings.Save(true); } }); DumpSkillsCommand = new RelayCommand( (parameter) => { PlayerInfoCache.DumpPlayerSkills(); UILoader.CloseWindow(); }); } catch (Exception ex) { Logger.LogError("Error creating Trinity View Model {0}", ex); } }
public static List <Trinity> AnalizeListOfFacts(string Source) { List <Trinity> Result = new List <Trinity>(); Trinity BufferTrinity; List <BorderOfTrinity> BT = new List <BorderOfTrinity>(); Source = Source.Trim(); if (Source.Length == 0) { throw new TPMException(); } // Ищем позиции запятых int LeftBorder = 0; BorderOfTrinity SomeBT; for (int i = 0; i < Source.Length; i++) { if (Source[i] == '&') { SomeBT = new BorderOfTrinity(); SomeBT.Left = LeftBorder; SomeBT.Right = i; BT.Add(SomeBT); LeftBorder = i; } } SomeBT = new BorderOfTrinity(); SomeBT.Left = LeftBorder; SomeBT.Right = Source.Length - 1; BT.Add(SomeBT); foreach (BorderOfTrinity CommaInterval in BT) { for (int i = CommaInterval.Left; i < CommaInterval.Right; i++) { if (Source[i] == '-') { CommaInterval.ListOfDefises.Add(i); } } if ((CommaInterval.ListOfDefises.Count < 1) || (CommaInterval.ListOfDefises.Count > 2)) { throw new TPMException(); } } string BufferTerm; int TypeCounter; int RightBorder; foreach (BorderOfTrinity CommaInterval in BT) { LeftBorder = CommaInterval.Left; TypeCounter = 0; BufferTrinity = new Trinity(); foreach (int CycleParameter in CommaInterval.ListOfDefises) { RightBorder = CycleParameter; if ((Source[LeftBorder] == '-') || (Source[LeftBorder] == '&')) { LeftBorder++; } if (!((Source[RightBorder] == '-') || (Source[RightBorder] == '&'))) { RightBorder--; } BufferTerm = Source.Substring(LeftBorder, RightBorder - LeftBorder).Trim(); if (BufferTerm.Length == 0) { throw new TPMException(); } if (TypeCounter == 0) { BufferTrinity.Atribute = BufferTerm; } if ((TypeCounter == 1)) { BufferTrinity.Object = BufferTerm; } if ((Source[RightBorder] == '-') || (Source[RightBorder] == '&')) { RightBorder++; } LeftBorder = RightBorder; TypeCounter++; } RightBorder = CommaInterval.Right + 1; if ((Source[LeftBorder] == '-') || (Source[LeftBorder] == '&')) { LeftBorder++; } if (Source[RightBorder - 1] == '&') { RightBorder--; } BufferTerm = Source.Substring(LeftBorder, RightBorder - LeftBorder).Trim(); if (BufferTerm.Length == 0) { throw new TPMException(); } if (TypeCounter == 1) { BufferTrinity.Value = BufferTerm; BufferTrinity.Object = String.Empty; } if ((TypeCounter == 2)) { BufferTrinity.Value = BufferTerm; } Result.Add(BufferTrinity); } return(Result); }
public void MoveTowards(Vector3 vMoveToTarget) { if (Trinity.Settings.Advanced.DisableAllMovement) { return; } if (!ZetaDia.IsInGame || !ZetaDia.Me.IsValid || ZetaDia.Me.IsDead || ZetaDia.IsLoadingWorld) { return; } if (UISafetyCheck()) { return; } TimeLastUsedPlayerMover = DateTime.UtcNow; LastMoveToTarget = vMoveToTarget; // Set the public variable vMoveToTarget = WarnAndLogLongPath(vMoveToTarget); // Store player current position // Store distance to current moveto target float destinationDistance = MyPosition.Distance2D(vMoveToTarget); // Do unstuckery things if (Trinity.Settings.Advanced.UnstuckerEnabled) { // See if we can reset the 10-limit unstuck counter, if >120 seconds since we last generated an unstuck location // this is used if we're NOT stuck... if (TotalAntiStuckAttempts > 1 && DateTime.UtcNow.Subtract(LastGeneratedStuckPosition).TotalSeconds >= 120) { TotalAntiStuckAttempts = 1; TimesReachedStuckPoint = 0; vSafeMovementLocation = Vector3.Zero; NavHelper.UsedStuckSpots = new List <GridPoint>(); Logger.Log(TrinityLogLevel.Info, LogCategory.Movement, "Resetting unstuck timers", true); } // See if we need to, and can, generate unstuck actions // check if we're stuck bool isStuck = UnstuckChecker(); if (isStuck) { // Record the time we last apparently couldn't move for a brief period of time LastRecordedAnyStuck = DateTime.UtcNow; // See if there's any stuck position to try and navigate to generated by random mover vSafeMovementLocation = UnstuckHandler(MyPosition, vMoveToTarget); if (vSafeMovementLocation == Vector3.Zero) { Logger.Log(TrinityLogLevel.Info, LogCategory.Movement, "Unable to find Unstuck point!", vSafeMovementLocation); return; } Logger.Log(TrinityLogLevel.Verbose, LogCategory.Movement, "SafeMovement Location set to {0}", vSafeMovementLocation); } // See if we can clear the total unstuckattempts if we haven't been stuck in over 6 minutes. if (DateTime.UtcNow.Subtract(LastRecordedAnyStuck).TotalSeconds >= 360) { TimesReachedMaxUnstucks = 0; } // Did we have a safe point already generated (eg from last loop through), if so use it as our current location instead if (vSafeMovementLocation != Vector3.Zero) { // Set our current movement target to the safe point we generated last cycle vMoveToTarget = vSafeMovementLocation; destinationDistance = MyPosition.Distance2D(vMoveToTarget); } // Get distance to current destination // Remove the stuck position if it's been reached, this bit of code also creates multiple stuck-patterns in an ever increasing amount if (vSafeMovementLocation != Vector3.Zero && destinationDistance <= 3f) { vSafeMovementLocation = Vector3.Zero; TimesReachedStuckPoint++; // Do we want to immediately generate a 2nd waypoint to "chain" anti-stucks in an ever-increasing path-length? if (TimesReachedStuckPoint <= TotalAntiStuckAttempts) { vSafeMovementLocation = NavHelper.FindSafeZone(true, TotalAntiStuckAttempts, MyPosition); vMoveToTarget = vSafeMovementLocation; } else { if (Trinity.Settings.Advanced.LogCategories.HasFlag(LogCategory.Movement)) { Logger.Log(TrinityLogLevel.Info, LogCategory.UserInformation, "Clearing old route and trying new path find to: " + LastMoveToTarget.ToString()); } // Reset the path and allow a whole "New" unstuck generation next cycle TimesReachedStuckPoint = 0; // And cancel unstucking for 9 seconds so DB can try to navigate CancelUnstuckerForSeconds = (9 * TotalAntiStuckAttempts); if (CancelUnstuckerForSeconds < 20) { CancelUnstuckerForSeconds = 20; } LastCancelledUnstucker = DateTime.UtcNow; Navigator.Clear(); Navigator.MoveTo(LastMoveToTarget, "original destination", false); return; } } } // don't use special movement within 10 seconds of being stuck bool cancelSpecialMovementAfterStuck = DateTime.UtcNow.Subtract(LastGeneratedStuckPosition).TotalMilliseconds > 10000; // See if we can use abilities like leap etc. for movement out of combat, but not in town if (Trinity.Settings.Combat.Misc.AllowOOCMovement && !Trinity.Player.IsInTown && !Trinity.DontMoveMeIAmDoingShit && cancelSpecialMovementAfterStuck) { bool bTooMuchZChange = (Math.Abs(MyPosition.Z - vMoveToTarget.Z) >= 4f); // Whirlwind for a barb, special context only if (Trinity.Settings.Combat.Barbarian.SprintMode != BarbarianSprintMode.CombatOnly && Trinity.Hotbar.Contains(SNOPower.Barbarian_Whirlwind) && Trinity.ObjectCache.Any(u => u.IsUnit && MathUtil.IntersectsPath(u.Position, u.Radius + 5f, Trinity.Player.Position, vMoveToTarget)) && Trinity.Player.PrimaryResource >= V.F("Barbarian.Whirlwind.MinFury") && !Trinity.IsWaitingForSpecial && V.B("Barbarian.Whirlwind.UseForMovement")) { ZetaDia.Me.UsePower(SNOPower.Barbarian_Whirlwind, vMoveToTarget, Trinity.CurrentWorldDynamicId, -1); SpellHistory.RecordSpell(SNOPower.Barbarian_Whirlwind); if (Trinity.Settings.Advanced.LogCategories.HasFlag(LogCategory.Movement)) { Logger.Log(TrinityLogLevel.Debug, LogCategory.Movement, "Using Whirlwind for OOC movement, distance={0}", destinationDistance); } return; } // Leap movement for a barb if (Trinity.Settings.Combat.Barbarian.UseLeapOOC && Trinity.Hotbar.Contains(SNOPower.Barbarian_Leap) && PowerManager.CanCast(SNOPower.Barbarian_Leap) && !ShrinesInArea(vMoveToTarget)) { Vector3 vThisTarget = vMoveToTarget; if (destinationDistance > 35f) { vThisTarget = MathEx.CalculatePointFrom(vMoveToTarget, MyPosition, 35f); } ZetaDia.Me.UsePower(SNOPower.Barbarian_Leap, vThisTarget, Trinity.CurrentWorldDynamicId, -1); SpellHistory.RecordSpell(SNOPower.Barbarian_Leap); if (Trinity.Settings.Advanced.LogCategories.HasFlag(LogCategory.Movement)) { Logger.Log(TrinityLogLevel.Debug, LogCategory.Movement, "Using Leap for OOC movement, distance={0}", destinationDistance); } return; } // Furious Charge movement for a barb if (Trinity.Settings.Combat.Barbarian.UseChargeOOC && Trinity.Hotbar.Contains(SNOPower.Barbarian_FuriousCharge) && !bTooMuchZChange && destinationDistance >= 20f && PowerManager.CanCast(SNOPower.Barbarian_FuriousCharge) && !ShrinesInArea(vMoveToTarget)) { Vector3 vThisTarget = vMoveToTarget; if (destinationDistance > 35f) { vThisTarget = MathEx.CalculatePointFrom(vMoveToTarget, MyPosition, 35f); } ZetaDia.Me.UsePower(SNOPower.Barbarian_FuriousCharge, vThisTarget, Trinity.CurrentWorldDynamicId, -1); SpellHistory.RecordSpell(SNOPower.Barbarian_FuriousCharge); if (Trinity.Settings.Advanced.LogCategories.HasFlag(LogCategory.Movement)) { Logger.Log(TrinityLogLevel.Debug, LogCategory.Movement, "Using Furious Charge for OOC movement, distance={0}", destinationDistance); } return; } bool hasTacticalAdvantage = HotbarSkills.PassiveSkills.Any(s => s == SNOPower.DemonHunter_Passive_TacticalAdvantage); int vaultDelay = hasTacticalAdvantage ? 2000 : Trinity.Settings.Combat.DemonHunter.VaultMovementDelay; // DemonHunter Vault if (Trinity.Hotbar.Contains(SNOPower.DemonHunter_Vault) && !bTooMuchZChange && Trinity.Settings.Combat.DemonHunter.VaultMode != DemonHunterVaultMode.CombatOnly && CombatBase.TimeSincePowerUse(SNOPower.DemonHunter_Vault) > vaultDelay && destinationDistance >= 18f && PowerManager.CanCast(SNOPower.DemonHunter_Vault) && !ShrinesInArea(vMoveToTarget) && // Don't Vault into avoidance/monsters if we're kiting (CombatBase.PlayerKiteDistance <= 0 || (CombatBase.PlayerKiteDistance > 0 && (!CacheData.TimeBoundAvoidance.Any(a => a.Position.Distance(vMoveToTarget) <= CombatBase.PlayerKiteDistance) || (!CacheData.TimeBoundAvoidance.Any(a => MathEx.IntersectsPath(a.Position, a.Radius, Trinity.Player.Position, vMoveToTarget))) || !CacheData.MonsterObstacles.Any(a => a.Position.Distance(vMoveToTarget) <= CombatBase.PlayerKiteDistance)))) ) { Vector3 vThisTarget = vMoveToTarget; if (destinationDistance > 35f) { vThisTarget = MathEx.CalculatePointFrom(vMoveToTarget, MyPosition, 35f); } ZetaDia.Me.UsePower(SNOPower.DemonHunter_Vault, vThisTarget, Trinity.CurrentWorldDynamicId, -1); SpellHistory.RecordSpell(SNOPower.DemonHunter_Vault); if (Trinity.Settings.Advanced.LogCategories.HasFlag(LogCategory.Movement)) { Logger.Log(TrinityLogLevel.Debug, LogCategory.Movement, "Using Vault for OOC movement, distance={0}", destinationDistance); } return; } // Tempest rush for a monk if (Trinity.Hotbar.Contains(SNOPower.Monk_TempestRush) && (Trinity.Settings.Combat.Monk.TROption == TempestRushOption.MovementOnly || Trinity.Settings.Combat.Monk.TROption == TempestRushOption.Always || (Trinity.Settings.Combat.Monk.TROption == TempestRushOption.TrashOnly && !TargetUtil.AnyElitesInRange(40f)))) { Vector3 vTargetAimPoint = vMoveToTarget; bool canRayCastTarget = true; vTargetAimPoint = TargetUtil.FindTempestRushTarget(); if (!CanChannelTempestRush && ((Trinity.Player.PrimaryResource >= Trinity.Settings.Combat.Monk.TR_MinSpirit && destinationDistance >= Trinity.Settings.Combat.Monk.TR_MinDist) || DateTime.UtcNow.Subtract(CacheData.AbilityLastUsed[SNOPower.Monk_TempestRush]).TotalMilliseconds <= 150) && canRayCastTarget && PowerManager.CanCast(SNOPower.Monk_TempestRush)) { CanChannelTempestRush = true; } else if ((CanChannelTempestRush && (Trinity.Player.PrimaryResource < 10f)) || !canRayCastTarget) { CanChannelTempestRush = false; } double lastUse = DateTime.UtcNow.Subtract(CacheData.AbilityLastUsed[SNOPower.Monk_TempestRush]).TotalMilliseconds; if (CanChannelTempestRush) { if (Trinity.SNOPowerUseTimer(SNOPower.Monk_TempestRush)) { LastTempestRushPosition = vTargetAimPoint; ZetaDia.Me.UsePower(SNOPower.Monk_TempestRush, vTargetAimPoint, Trinity.CurrentWorldDynamicId, -1); SpellHistory.RecordSpell(SNOPower.Monk_TempestRush); // simulate movement speed of 30 SpeedSensor lastSensor = SpeedSensors.OrderByDescending(s => s.Timestamp).FirstOrDefault(); SpeedSensors.Add(new SpeedSensor() { Location = MyPosition, TimeSinceLastMove = new TimeSpan(0, 0, 0, 0, 1000), Distance = 5f, WorldID = Trinity.CurrentWorldDynamicId }); if (Trinity.Settings.Advanced.LogCategories.HasFlag(LogCategory.Movement)) { Logger.Log(TrinityLogLevel.Debug, LogCategory.Movement, "Using Tempest Rush for OOC movement, distance={0:0} spirit={1:0} cd={2} lastUse={3:0} V3={4} vAim={5}", destinationDistance, Trinity.Player.PrimaryResource, PowerManager.CanCast(SNOPower.Monk_TempestRush), lastUse, vMoveToTarget, vTargetAimPoint); } return; } else { return; } } else { if (Trinity.Settings.Advanced.LogCategories.HasFlag(LogCategory.Movement)) { Logger.Log(TrinityLogLevel.Debug, LogCategory.Movement, "Tempest rush failed!: {0:00.0} / {1} distance: {2:00.0} / {3} Raycast: {4} MS: {5:0.0} lastUse={6:0}", Trinity.Player.PrimaryResource, Trinity.Settings.Combat.Monk.TR_MinSpirit, destinationDistance, Trinity.Settings.Combat.Monk.TR_MinDist, canRayCastTarget, GetMovementSpeed(), lastUse); } Trinity.MaintainTempestRush = false; } // Always set this from PlayerMover Trinity.LastTempestRushLocation = vTargetAimPoint; } // Dashing Strike OOC if (CombatBase.CanCast(SNOPower.X1_Monk_DashingStrike) && Trinity.Settings.Combat.Monk.UseDashingStrikeOOC && destinationDistance > 15f) { ZetaDia.Me.UsePower(SNOPower.X1_Monk_DashingStrike, vMoveToTarget, Trinity.CurrentWorldDynamicId, -1); SpellHistory.RecordSpell(SNOPower.X1_Monk_DashingStrike); if (Trinity.Settings.Advanced.LogCategories.HasFlag(LogCategory.Movement)) { Logger.Log(TrinityLogLevel.Debug, LogCategory.Movement, "Using Dashing Strike for OOC movement, distance={0}", destinationDistance); } } bool hasWormHole = HotbarSkills.AssignedSkills.Any(s => s.Power == SNOPower.Wizard_Teleport && s.RuneIndex == 4); bool hasCalamity = HotbarSkills.AssignedSkills.Any(s => s.Power == SNOPower.Wizard_Teleport && s.RuneIndex == 0); // Teleport for a wizard if (!hasCalamity && CombatBase.CanCast(SNOPower.Wizard_Teleport, CombatBase.CanCastFlags.NoTimer) && CombatBase.TimeSincePowerUse(SNOPower.Wizard_Teleport) > 250 && destinationDistance >= 10f && !ShrinesInArea(vMoveToTarget)) { var maxTeleportRange = 75f; Vector3 vThisTarget = vMoveToTarget; if (destinationDistance > maxTeleportRange) { vThisTarget = MathEx.CalculatePointFrom(vMoveToTarget, MyPosition, maxTeleportRange); } ZetaDia.Me.UsePower(SNOPower.Wizard_Teleport, vThisTarget, Trinity.CurrentWorldDynamicId, -1); SpellHistory.RecordSpell(SNOPower.Wizard_Teleport); if (Trinity.Settings.Advanced.LogCategories.HasFlag(LogCategory.Movement)) { Logger.Log(TrinityLogLevel.Debug, LogCategory.Movement, "Using Teleport for OOC movement, distance={0}", destinationDistance); } return; } // Archon Teleport for a wizard if (Trinity.Hotbar.Contains(SNOPower.Wizard_Archon_Teleport) && DateTime.UtcNow.Subtract(CacheData.AbilityLastUsed[SNOPower.Wizard_Archon_Teleport]).TotalMilliseconds >= CombatBase.GetSNOPowerUseDelay(SNOPower.Wizard_Archon_Teleport) && destinationDistance >= 20f && PowerManager.CanCast(SNOPower.Wizard_Archon_Teleport) && !ShrinesInArea(vMoveToTarget)) { Vector3 vThisTarget = vMoveToTarget; if (destinationDistance > 35f) { vThisTarget = MathEx.CalculatePointFrom(vMoveToTarget, MyPosition, 35f); } ZetaDia.Me.UsePower(SNOPower.Wizard_Archon_Teleport, vThisTarget, Trinity.CurrentWorldDynamicId, -1); SpellHistory.RecordSpell(SNOPower.Wizard_Archon_Teleport); if (Trinity.Settings.Advanced.LogCategories.HasFlag(LogCategory.Movement)) { Logger.Log(TrinityLogLevel.Debug, LogCategory.Movement, "Using Archon Teleport for OOC movement, distance={0}", destinationDistance); } return; } } if (MyPosition.Distance2D(vMoveToTarget) > 1f) { // Default movement ZetaDia.Me.UsePower(SNOPower.Walk, vMoveToTarget, Trinity.CurrentWorldDynamicId, -1); if (Trinity.Settings.Advanced.LogCategories.HasFlag(LogCategory.Movement)) { Logger.Log(TrinityLogLevel.Debug, LogCategory.Movement, "Moved to:{0} dir:{1} Speed:{2:0.00} Dist:{3:0} ZDiff:{4:0} CanStand:{5} Raycast:{6}", NavHelper.PrettyPrintVector3(vMoveToTarget), MathUtil.GetHeadingToPoint(vMoveToTarget), MovementSpeed, MyPosition.Distance2D(vMoveToTarget), Math.Abs(MyPosition.Z - vMoveToTarget.Z), Trinity.MainGridProvider.CanStandAt(Trinity.MainGridProvider.WorldToGrid(vMoveToTarget.ToVector2())), !Navigator.Raycast(MyPosition, vMoveToTarget) ); } } else { if (Trinity.Settings.Advanced.LogCategories.HasFlag(LogCategory.Movement)) { Logger.Log(TrinityLogLevel.Debug, LogCategory.Movement, "Reached MoveTowards Destination {0} Current Speed: {1:0.0}", vMoveToTarget, MovementSpeed); } } }
public bool ShouldStashItem(ACDItem item, ItemEvaluationType evaluationType) { ItemEvents.ResetTownRun(); if (Current.ItemIsProtected(item)) { return(false); } // Vanity Items if (DataDictionary.VanityItems.Any(i => item.InternalName.StartsWith(i))) { return(false); } if (Trinity.Settings.Loot.ItemFilterMode == ItemFilterMode.DemonBuddy) { return(Current.ShouldStashItem(item)); } CachedACDItem cItem = CachedACDItem.GetCachedItem(item); // Now look for Misc items we might want to keep GItemType tItemType = cItem.TrinityItemType; // DetermineItemType(cItem.InternalName, cItem.DBItemType, cItem.FollowerType); GItemBaseType tBaseType = cItem.TrinityItemBaseType; // DetermineBaseType(trinityItemType); bool isEquipment = (tBaseType == GItemBaseType.Armor || tBaseType == GItemBaseType.Jewelry || tBaseType == GItemBaseType.Offhand || tBaseType == GItemBaseType.WeaponOneHand || tBaseType == GItemBaseType.WeaponRange || tBaseType == GItemBaseType.WeaponTwoHand); if (cItem.TrinityItemType == GItemType.HoradricCache && Trinity.Settings.Loot.TownRun.OpenHoradricCaches) { Logger.Log(TrinityLogLevel.Info, LogCategory.UserInformation, "{0} [{1}] = (ignoring Horadric Cache)", cItem.RealName, cItem.InternalName); return(false); } // Stash all unidentified items - assume we want to keep them since we are using an identifier over-ride if (cItem.IsUnidentified) { if (evaluationType == ItemEvaluationType.Keep) { Logger.Log(TrinityLogLevel.Info, LogCategory.UserInformation, "{0} [{1}] = (autokeep unidentified items)", cItem.RealName, cItem.InternalName); } return(true); } if (tItemType == GItemType.StaffOfHerding) { if (evaluationType == ItemEvaluationType.Keep) { Logger.Log(TrinityLogLevel.Info, LogCategory.ItemValuation, "{0} [{1}] [{2}] = (autokeep staff of herding)", cItem.RealName, cItem.InternalName, tItemType); } return(true); } if (tItemType == GItemType.CraftingMaterial) { if (evaluationType == ItemEvaluationType.Keep) { Logger.Log(TrinityLogLevel.Info, LogCategory.ItemValuation, "{0} [{1}] [{2}] = (autokeep craft materials)", cItem.RealName, cItem.InternalName, tItemType); } return(true); } if (tItemType == GItemType.Emerald || tItemType == GItemType.Amethyst || tItemType == GItemType.Topaz || tItemType == GItemType.Ruby || tItemType == GItemType.Diamond) { if (evaluationType == ItemEvaluationType.Keep) { Logger.Log(TrinityLogLevel.Info, LogCategory.ItemValuation, "{0} [{1}] [{2}] = (autokeep gems)", cItem.RealName, cItem.InternalName, tItemType); } return(true); } if (tItemType == GItemType.CraftTome) { if (evaluationType == ItemEvaluationType.Keep) { Logger.Log(TrinityLogLevel.Info, LogCategory.ItemValuation, "{0} [{1}] [{2}] = (autokeep tomes)", cItem.RealName, cItem.InternalName, tItemType); } return(true); } if (tItemType == GItemType.InfernalKey) { if (evaluationType == ItemEvaluationType.Keep) { Logger.Log(TrinityLogLevel.Info, LogCategory.UserInformation, "{0} [{1}] [{2}] = (autokeep infernal key)", cItem.RealName, cItem.InternalName, tItemType); } return(true); } if (tItemType == GItemType.HealthPotion) { if (evaluationType == ItemEvaluationType.Keep) { Logger.Log(TrinityLogLevel.Info, LogCategory.ItemValuation, "{0} [{1}] [{2}] = (ignoring potions)", cItem.RealName, cItem.InternalName, tItemType); } return(false); } if (tItemType == GItemType.CraftingPlan && cItem.Quality >= ItemQuality.Legendary) { if (evaluationType == ItemEvaluationType.Keep) { Logger.Log(TrinityLogLevel.Info, LogCategory.UserInformation, "{0} [{1}] [{2}] = (autokeep legendary plans)", cItem.RealName, cItem.InternalName, tItemType); } return(true); } if (Trinity.Settings.Loot.ItemFilterMode == ItemFilterMode.TrinityWithItemRules) { Interpreter.InterpreterAction action = Trinity.StashRule.checkItem(item, evaluationType); if (evaluationType == ItemEvaluationType.Keep) { Logger.Log(TrinityLogLevel.Info, LogCategory.UserInformation, "{0} [{1}] [{2}] = (" + action + ")", cItem.AcdItem.Name, cItem.AcdItem.InternalName, cItem.AcdItem.ItemType); } switch (action) { case Interpreter.InterpreterAction.KEEP: return(true); case Interpreter.InterpreterAction.TRASH: return(false); case Interpreter.InterpreterAction.SCORE: break; } } if (tItemType == GItemType.CraftingPlan) { if (evaluationType == ItemEvaluationType.Keep) { Logger.Log(TrinityLogLevel.Info, LogCategory.UserInformation, "{0} [{1}] [{2}] = (autokeep plans)", cItem.RealName, cItem.InternalName, tItemType); } return(true); } // Stashing Whites, auto-keep if (Trinity.Settings.Loot.TownRun.StashWhites && isEquipment && cItem.Quality <= ItemQuality.Superior) { Logger.Log(TrinityLogLevel.Info, LogCategory.UserInformation, "{0} [{1}] [{2}] = (stashing whites)", cItem.RealName, cItem.InternalName, tItemType); return(true); } // Else auto-trash if (cItem.Quality <= ItemQuality.Superior && (isEquipment || cItem.TrinityItemBaseType == GItemBaseType.FollowerItem)) { Logger.Log(TrinityLogLevel.Info, LogCategory.UserInformation, "{0} [{1}] [{2}] = (trash whites)", cItem.RealName, cItem.InternalName, tItemType); return(false); } // Stashing blues, auto-keep if (Trinity.Settings.Loot.TownRun.StashBlues && isEquipment && cItem.Quality >= ItemQuality.Magic1 && cItem.Quality <= ItemQuality.Magic3) { Logger.Log(TrinityLogLevel.Info, LogCategory.UserInformation, "{0} [{1}] [{2}] = (stashing blues)", cItem.RealName, cItem.InternalName, tItemType); return(true); } // Else auto trash if (cItem.Quality >= ItemQuality.Magic1 && cItem.Quality <= ItemQuality.Magic3 && (isEquipment || cItem.TrinityItemBaseType == GItemBaseType.FollowerItem)) { Logger.Log(TrinityLogLevel.Info, LogCategory.UserInformation, "{0} [{1}] [{2}] = (trashing blues)", cItem.RealName, cItem.InternalName, tItemType); return(false); } // Force salvage Rares if (Trinity.Settings.Loot.TownRun.ForceSalvageRares && cItem.Quality >= ItemQuality.Rare4 && cItem.Quality <= ItemQuality.Rare6 && (isEquipment || cItem.TrinityItemBaseType == GItemBaseType.FollowerItem)) { Logger.Log(TrinityLogLevel.Info, LogCategory.UserInformation, "{0} [{1}] [{2}] = (force salvage rare)", cItem.RealName, cItem.InternalName, tItemType); return(false); } if (cItem.Quality >= ItemQuality.Legendary) { if (evaluationType == ItemEvaluationType.Keep) { Logger.Log(TrinityLogLevel.Info, LogCategory.UserInformation, "{0} [{1}] [{2}] = (autokeep legendaries)", cItem.RealName, cItem.InternalName, tItemType); } return(true); } // Ok now try to do some decent item scoring based on item types double iNeedScore = Trinity.ScoreNeeded(item.ItemBaseType); double iMyScore = ItemValuation.ValueThisItem(cItem, tItemType); if (evaluationType == ItemEvaluationType.Keep) { Logger.Log(TrinityLogLevel.Verbose, LogCategory.ItemValuation, "{0} [{1}] [{2}] = {3}", cItem.RealName, cItem.InternalName, tItemType, iMyScore); } if (iMyScore >= iNeedScore) { return(true); } // If we reached this point, then we found no reason to keep the item! return(false); }