/// <summary> /// Moves to a position, finds actor by Id and interacts with it /// </summary> /// <param name="actorId">id of actor to interact with</param> /// <param name="position">position from which to interact</param> /// <param name="interactLimit">maximum number of times to interact</param> public static async Task <bool> Execute(Vector3 position, SNOActor actorId, int interactLimit = 5) { if (position == Vector3.Zero) { return(false); } if (interactLimit < 1) { interactLimit = 5; } if (Core.Player.IsInTown) { GameUI.CloseVendorWindow(); } DiaObject actor; while ((actor = ZetaDia.Actors.GetActorsOfType <DiaObject>(true) .FirstOrDefault(a => (SNOActor)a.ActorSnoId == actorId) ) == null && await CommonCoroutines.MoveAndStop(position, 40f, "Close to target") != MoveResult.ReachedDestination) { await Coroutine.Yield(); } if (actor != null) { return(await Execute(actor, interactLimit)); } Core.Logger.Verbose("Interaction Failed: Actor not found with Id={0}", actorId); return(false); }
private async Task <bool> MoveProducer() { Core.Logger.Verbose($"Moving to Actor: {Actor} {Actor.Position}"); while (await CommonCoroutines.MoveAndStop(Actor.Position, 5f, Actor.Name) != MoveResult.ReachedDestination) { await Coroutine.Yield(); } return(true); }
public static async Task <bool> TakeReturnPortal() { if (!ZetaDia.IsInTown) { return(false); } var portalRef = TownInfo.ReturnPortal; var actor = portalRef?.GetActor(); if (actor == null || !actor.IsFullyValid()) { Core.Logger.Debug("Couldn't find a return portal"); return(false); } Core.Logger.Log("Found a hearth portal, lets use it."); if (!await MoveToAndInteract.Execute(actor, 2f, 10)) { Core.Logger.Log("Failed to move to return portal :("); return(false); } Core.PlayerMover.MoveStop(); if (actor.IsFullyValid() && !actor.Interact()) { Core.Logger.Debug("Failed to interact with return portal."); } await Coroutine.Sleep(1000); if (ZetaDia.IsInTown && !ZetaDia.Globals.IsLoadingWorld) { Core.Logger.Log("Trying again to use return portal."); var gizmo = ZetaDia.Actors.GetActorsOfType <DiaGizmo>().FirstOrDefault(g => g.ActorInfo.GizmoType == GizmoType.HearthPortal); if (gizmo != null) { await CommonCoroutines.MoveAndStop(gizmo.Position, 2f, "Portal Position"); await Coroutine.Sleep(1000); gizmo.Interact(); gizmo.Interact(); } } await Coroutine.Wait(5000, () => !ZetaDia.Globals.IsLoadingWorld); return(true); }
public override async Task <bool> HandleAvoiding() { if (Core.Player.Actor == null || !IsAvoidanceRequired) { return(false); } var safe = (!Core.Player.IsTakingDamage || Core.Player.CurrentHealthPct > 0.5f) && Core.Player.Actor != null && !Core.Player.Actor.IsInCriticalAvoidance; if (!TrinityCombat.IsInCombat && Core.Player.Actor.IsAvoidanceOnPath && safe) { Core.Logger.Log(LogCategory.Avoidance, "Waiting for avoidance to clear (out of combat)"); return(await CommonCoroutines.MoveAndStop(Core.Avoidance.Avoider.SafeSpot, 5f, "Safe Spot") != MoveResult.ReachedDestination); } Core.Logger.Log(LogCategory.Avoidance, "Avoiding"); return(await CommonCoroutines.MoveAndStop(Core.Avoidance.Avoider.SafeSpot, 5f, "Safe Spot") != MoveResult.ReachedDestination); }
public async Task <bool> WaitForRiftBossSpawn() { if (Core.Rift.IsInRift && CurrentTarget.IsBoss) { if (CurrentTarget.IsSpawningBoss) { Core.Logger.Verbose(LogCategory.Targetting, "Waiting while rift boss spawn"); if (Core.Avoidance.Avoider.TryGetSafeSpot(out Vector3 safeSpot, 30f, 100f, CurrentTarget.Position)) { return(await CommonCoroutines.MoveAndStop(safeSpot, 5f, "SafeSpot") != MoveResult.ReachedDestination); } return(true); } } return(false); }
public virtual async Task <bool> HandleKiting() { if (!Core.Avoidance.Avoider.ShouldKite) { return(false); } if (!Core.Avoidance.Avoider.TryGetSafeSpot(out Vector3 safespot) || safespot.Distance(ZetaDia.Me.Position) < 5f) { return(false); } Core.Logger.Log(LogCategory.Avoidance, "Kiting"); await CastDefensiveSpells(); return(await CommonCoroutines.MoveAndStop(Core.Avoidance.Avoider.SafeSpot, 5f, "Kiting") != MoveResult.ReachedDestination); }
public static async Task <bool> Execute() { if (!IsClearing) { return(false); } Core.Logger.Debug("Clear task executed"); var noMonsters = !ZetaDia.Actors.GetActorsOfType <DiaUnit>().Any(u => u?.CommonData != null && u.CommonData.IsValid && u.IsAlive && u.IsHostile && u.Distance < 70f); if (noMonsters) { Core.Logger.Debug($"No Monsters nearby, go back to portal position. Distance={StartPosition.Distance(ZetaDia.Me.Position)}"); await CommonCoroutines.MoveAndStop(StartPosition, 15f, "Town Portal Position"); Stop(); return(false); } var clearFinished = DateTime.UtcNow.Subtract(ClearStarted).TotalSeconds > ClearTimeSeconds; if (clearFinished) { Core.Logger.Debug("Clear timer finished, go back to portal position. Distance={StartPosition.Distance(ZetaDia.Me.Position)}"); await CommonCoroutines.MoveAndStop(StartPosition, 15f, "Town Portal Position"); Stop(); return(false); } var worldChanged = ZetaDia.Globals.WorldSnoId != StartWorld; if (worldChanged) { Core.Logger.Debug("World Changed, Stop Clearing"); Stop(); return(false); } return(true); }
public virtual async Task <bool> HandleAvoiding() { if (Core.Player.Actor == null || !IsAvoidanceRequired) { return(false); } var safe = (!Core.Player.IsTakingDamage || Core.Player.CurrentHealthPct > 0.5f) && Core.Player.Actor != null && !Core.Player.Actor.IsInCriticalAvoidance; if (!TrinityCombat.IsInCombat && Core.Player.Actor.IsAvoidanceOnPath && safe) { Core.Logger.Log(LogCategory.Avoidance, "Waiting for avoidance to clear (out of combat)"); Core.Avoidance.Invalidate(); return(await CommonCoroutines.MoveAndStop(Core.Avoidance.Avoider.SafeSpot, 5f, "Safe Spot") != MoveResult.ReachedDestination); } if (Core.Avoidance.Avoider.SafeSpot.Distance(Player.Position) < 5f) { return(false); } Core.Logger.Log(LogCategory.Avoidance, "Moving away from Critical Avoidance."); MoveResult res; if ((res = await CommonCoroutines.MoveAndStop(Core.Avoidance.Avoider.SafeSpot, 5f, "Safe Spot")) != MoveResult.ReachedDestination && res != MoveResult.Failed) { return(true); } await CastDefensiveSpells(); return(true); }
private async Task <bool> MainCoroutine() { if (ZetaDia.IsLoadingWorld || !ZetaDia.IsInTown) { Logger.Verbose("We're not in town!"); _isDone = true; return(false); } if (ZetaDia.Me.IsParticipatingInTieredLootRun) { Logger.Debug("Already in Greater Rift!"); _isDone = true; return(false); } CheckForRiftPortal(); //[22559C94] GizmoType: LootRunSwitch Name: x1_OpenWorld_LootRunObelisk_B-91 ActorSNO: 364715 Distance: 4.497307 Position: <359.9, 262.766, -0.0996094> Barracade: False Radius: 9.874258 var destination = Vector3.Zero; DiaObject actor; switch (ZetaDia.CurrentAct) { case Act.A3: case Act.A4: destination = new Vector3(463.4105f, 387.2089f, 0.4986931f); break; case Act.A5: destination = new Vector3(602.5745f, 751.5975f, 2.620764f); break; case Act.A1: destination = new Vector3(372.5257f, 591.0864f, 24.04533f); break; case Act.A2: destination = new Vector3(353.7471f, 262.6955f, -0.3242264f); break; default: actor = GetObeliskActor(); if (actor != null) { destination = actor.Position; } else { Logger.Error("Unable to find Rift Obelisk"); return(false); } break; } if (ZetaDia.Me.Position.Distance(destination) > 15f) { Logger.Verbose("Starting movement to Rift Obelisk"); while (ZetaDia.Me.Position.Distance(destination) > 15f) { await CommonCoroutines.MoveAndStop(destination, 15f); await Coroutine.Yield(); } Logger.Verbose("Finished movement to Rift Obelisk"); } actor = GetObeliskActor(); if (actor == null || !actor.IsValid) { Logger.Error("Unable to find Rift Obelisk"); return(false); } bool readyToStart = false; for (int j = 0; j < 10; j++) { if (UIElement.FromHash(0x3182F223039F15F0).IsVisible) { readyToStart = true; break; } Logger.Verbose("Interacting with rift obelisk"); actor.Interact(); await Coroutine.Sleep(500); } if (readyToStart) { ZetaDia.Me.OpenRift(_level); await Coroutine.Sleep(1000); } return(false); }
public async Task <bool> CastTrinityPower(TrinityPower power, string type = "") { if (power == null || power.SNOPower == SNOPower.None) { Core.Logger.Log(LogCategory.Spells, $"Power was null or SNOPower.None"); return(false); } if (!CanCast(power.SNOPower)) { if (!Core.Player.IsPowerUseDisabled) { Core.Logger.Log(LogCategory.Spells, $"CanCast failed for {power.SNOPower}"); } return(false); } if (power.AssignedInDifferentWorld) { Core.Logger.Log(LogCategory.Spells, $"World has changed since power was created"); return(false); } var distance = power.TargetPosition.Distance(Core.Player.Position); var castInfo = $"{type} {power}".Trim(); var target = Core.Actors.RActorByAcdId <TrinityActor>(power.TargetAcdId); if (target != null && target.IsValid) { castInfo += $" on {target}"; // Store found unit's position for SpellHistory queries. power.TargetPosition = target.Position; if (!TrinityCombat.Targeting.IsInRange(target, power)) { Core.Logger.Log(LogCategory.Movement, $"Moving to {castInfo}"); return(await CommonCoroutines.MoveAndStop(target.Position, power.MinimumRange, "AttackPosition") == MoveResult.ReachedDestination); } } else if (power.TargetPosition != Vector3.Zero) { if (distance > TrinityCombat.Targeting.MaxTargetDistance) { Core.Logger.Log(LogCategory.Spells, $"Target is way too far away ({distance})"); return(false); } castInfo += $" Dist:{Core.Player.Position.Distance(power.TargetPosition)}"; if (!TrinityCombat.Targeting.IsInRange(power.TargetPosition, power)) { Core.Logger.Log(LogCategory.Movement, $"Moving to position for {castInfo}"); return(await CommonCoroutines.MoveAndStop(power.TargetPosition, power.MinimumRange, "AttackPosition") == MoveResult.ReachedDestination); } } if (power.ShouldWaitBeforeUse) { Core.Logger.Verbose(LogCategory.Spells, $"Waiting before power for {power.WaitTimeBeforeRemaining}"); await Coroutine.Sleep((int)power.WaitTimeBeforeRemaining); } if (power.SNOPower == SNOPower.Walk) { Core.Logger.Verbose(LogCategory.Movement, $"Walk - arrived at Destination doing nothing {castInfo}"); return(true); } if (!CastPower(power.SNOPower, power.TargetPosition, power.TargetAcdId)) { Core.Logger.Verbose(LogCategory.Spells, $"Failed to cast {castInfo}"); return(false); } Core.Logger.Warn(LogCategory.Spells, $"Cast {castInfo}"); if (power.SNOPower == SNOPower.Axe_Operate_Gizmo && Core.StuckHandler.IsStuck) { Core.Logger.Verbose(LogCategory.Movement, $"Interaction Stuck Detected. {castInfo}"); await Core.StuckHandler.DoUnstick(); return(false); } if (power.ShouldWaitAfterUse) { Core.Logger.Verbose(LogCategory.Spells, $"Waiting after power for {power.WaitTimeAfterRemaining}"); await Coroutine.Sleep((int)power.WaitTimeAfterRemaining); } if (power.ShouldWaitForAttackToFinish) { Core.Logger.Log(LogCategory.Spells, $"Waiting for Attack to Finish"); await Coroutine.Wait(1000, () => ZetaDia.Me.IsCasting); } return(true); }
/// <summary> /// Moves items from the Stash to the Backpack /// </summary> /// <param name="itemIds">list of items to withdraw</param> /// <param name="maxAmount">amount to withdraw up to (including counts already in backpack)</param> /// <returns></returns> public static async Task <bool> TakeItemsFromStash(IEnumerable <SNOActor> itemIds, int maxAmount) { if (!ZetaDia.IsInGame || !ZetaDia.IsInTown) { return(true); } while (await CommonCoroutines.MoveAndStop( TownInfo.Stash.InteractPosition, TownInfo.Stash.GetActor().InteractDistance, "Stash") != MoveResult.ReachedDestination) { await Coroutine.Yield(); } var stash = TownInfo.Stash?.GetActor(); if (stash == null) { Core.Logger.Log("[TakeItemsFromStash] Unable to find Stash"); return(false); } if (!UIElements.StashWindow.IsVisible && TownInfo.Stash.Distance <= 10f) { await MoveToAndInteract.Execute(TownInfo.Stash); } if (!UIElements.StashWindow.IsVisible && TownInfo.Stash.Distance <= 10f) { Core.Logger.Log("[TakeItemsFromStash] Stash window not open, interacting"); stash.Interact(); } var itemIdsHashSet = new HashSet <SNOActor>(itemIds); var amountWithdrawn = itemIdsHashSet.ToDictionary(k => k, v => (long)0); var overageTaken = itemIdsHashSet.ToDictionary(k => k, v => false); var lastStackTaken = itemIdsHashSet.ToDictionary(k => k, v => default(ACDItem)); foreach (var item in InventoryManager.Backpack .Where(i => i.ACDId != 0 && i.IsValid && itemIdsHashSet.Contains(i.ActorSnoId)) .ToList()) { amountWithdrawn[item.ActorSnoId] += item.ItemStackQuantity; lastStackTaken[item.ActorSnoId] = item; } foreach (var item in InventoryManager.StashItems .Where(i => i.ACDId != 0 && i.IsValid && itemIdsHashSet.Contains(i.ActorSnoId)) .ToList()) { try { if (!item.IsValid || item.IsDisposed) { continue; } var stackSize = Math.Max(1, item.ItemStackQuantity); var numTakenAlready = amountWithdrawn[item.ActorSnoId]; // We have enough of this material already var alreadyTakenEnough = numTakenAlready >= maxAmount; if (alreadyTakenEnough) { continue; } // We have enough of everything already. if (amountWithdrawn.All(i => i.Value >= maxAmount)) { break; } // Only take up to the required amount. var willBeOverMax = numTakenAlready + stackSize > maxAmount; if (willBeOverMax && overageTaken[item.ActorSnoId]) { continue; } var lastItem = lastStackTaken[item.ActorSnoId]; var amountRequiredToMax = maxAmount - numTakenAlready; if (willBeOverMax && lastItem != null && lastItem.IsValid && !lastItem.IsDisposed && stackSize > amountRequiredToMax) { // Tried InventoryManager.SplitStack but it didnt work, reverting to moving onto existing stacks. var amountToSplit = stackSize - lastItem.ItemStackQuantity; Core.Logger.Log($"[TakeItemsFromStash] Merging Stash Stack {item.Name} ({item.ActorSnoId}) onto Backpack Stack. StackSize={amountToSplit} WithdrawnAlready={numTakenAlready} InternalName={item.InternalName} Id={item.ActorSnoId} Quality={item.ItemQualityLevel} AncientRank={item.AncientRank}"); InventoryManager.MoveItem( item.AnnId, ZetaDia.Me.CommonData.AnnId, InventorySlot.BackpackItems, lastItem.InventoryColumn, lastItem.InventoryRow); amountWithdrawn[item.ActorSnoId] += amountToSplit; overageTaken[item.ActorSnoId] = true; } else { if (item.IsValid && !item.IsDisposed) { Core.Logger.Log($"[TakeItemsFromStash] Removing {item.Name} ({item.ActorSnoId}) from stash. StackSize={stackSize} WithdrawnAlready={numTakenAlready} InternalName={item.InternalName} Id={item.ActorSnoId} AnnId={item.AnnId} Quality={item.ItemQualityLevel} AncientRank={item.AncientRank}"); // Quick withdraw broken? //InventoryManager.QuickWithdraw(item); var newPosition = TrinityCombat.Loot.FindBackpackSlot(item.IsTwoSquareItem); InventoryManager.MoveItem( item.AnnId, ZetaDia.Me.CommonData.AnnId, InventorySlot.BackpackItems, (int)newPosition.X, (int)newPosition.Y); amountWithdrawn[item.ActorSnoId] += stackSize; lastStackTaken[item.ActorSnoId] = item; } } await Coroutine.Yield(); } catch (Exception ex) { Core.Logger.Error(ex.ToString()); } } await Coroutine.Yield(); return(true); }
private async Task <bool> GetItemFromStashRoutine() { if (!ZetaDia.IsInGame) { return(false); } if (ZetaDia.IsLoadingWorld) { return(false); } if (!ZetaDia.IsInTown) { _isDone = true; return(false); } if (ZetaDia.Me == null) { return(false); } if (!ZetaDia.Me.IsValid) { return(false); } // Validate parameters if (GameBalanceId == 0 && ActorId == 0 && !GreaterRiftKey) { Logger.Error("GetItemFromStash: invalid parameters. Please specify at least gameBalanceId=\"\" or actorId=\"\" with valid ID numbers or set greaterRiftKey=\"True\""); _isDone = true; return(true); } var backPackCount = ZetaDia.Me.Inventory.Backpack.Where(ItemMatcherFunc).Sum(i => i.ItemStackQuantity); // Check to see if we already have the stack in our backpack if (StackCount != 0 && backPackCount >= StackCount) { Logger.Log("Already have {0} items in our backpack (GameBalanceId={1} ActorSNO={2} GreaterRiftKey={3})", backPackCount, GameBalanceId, ActorId, GreaterRiftKey); _isDone = true; return(true); } // Go to Town if (!ZetaDia.IsInTown) { await CommonCoroutines.UseTownPortal("Returning to Town to get Item"); } // Move to Stash if (StashLocation.Distance2D(ZetaDia.Me.Position) > 10f) { await CommonCoroutines.MoveAndStop(StashLocation, 10f, "Stash Location"); } if (StashLocation.Distance2D(ZetaDia.Me.Position) <= 10f && SharedStash == null) { Logger.Error("Shared Stash actor is null!"); } // Open Stash if (StashLocation.Distance2D(ZetaDia.Me.Position) <= 10f && SharedStash != null && !UIElements.StashWindow.IsVisible) { Logger.Log("Opening Stash"); SharedStash.Interact(); await Coroutine.Sleep(500); } if (UIElements.StashWindow.IsVisible) { Logger.Debug("Stash window is visible"); var itemList = ZetaDia.Me.Inventory.StashItems.Where(ItemMatcherFunc).ToList(); var firstItem = itemList.FirstOrDefault(); // Check to see if we have the item in the stash bool invalidGameBalanceId = false, invalidActorId = false; if (GameBalanceId != 0 && itemList.All(item => item.GameBalanceId != GameBalanceId)) { Logger.Error("Unable to find item in stash with GameBalanceId {0}", GameBalanceId); invalidGameBalanceId = true; } if (ActorId != 0 && itemList.All(item => item.ActorSNO != ActorId)) { Logger.Error("Unable to find item in stash with ActorSNO {0}", ActorId); invalidActorId = true; } if (firstItem == null || (invalidGameBalanceId && invalidActorId)) { _isDone = true; return(true); } Vector2 freeItemSlot = Helpers.ItemManager.FindValidBackpackLocation(firstItem.IsTwoSquareItem); if (freeItemSlot.X == -1 && freeItemSlot.Y == -1) { Logger.Log("No free slots to move items to"); _isDone = true; return(true); } var itemCount = 0; while ((StackCount == 0 || StackCount > backPackCount) && (MaxItems <= 0 || itemCount < MaxItems)) { bool highestFirst = QuestToolsSettings.Instance.UseHighestKeystone; var itemsList = ZetaDia.Me.Inventory.StashItems.Where(ItemMatcherFunc).ToList(); ACDItem item; if (GreaterRiftKey && highestFirst) { item = itemsList.OrderByDescending(i => i.TieredLootRunKeyLevel) .ThenBy(i => i.ItemStackQuantity) .FirstOrDefault(); } else if (GreaterRiftKey && !highestFirst) { item = itemsList.OrderBy(i => i.TieredLootRunKeyLevel) .ThenBy(i => i.ItemStackQuantity) .FirstOrDefault(); } else { item = itemsList.OrderBy(i => i.ItemStackQuantity).FirstOrDefault(); } if (item == null) { break; } Logger.Debug("Withdrawing item {0} from stash {0}", item.Name); ZetaDia.Me.Inventory.QuickWithdraw(item); itemCount++; await Coroutine.Yield(); backPackCount = ZetaDia.Me.Inventory.Backpack.Where(ItemMatcherFunc).Sum(i => i.ItemStackQuantity); } if (MaxItems > 0 && itemCount >= MaxItems) { _isDone = true; Logger.Log("Have max items of {0} in backpack", itemCount); return(true); } if (backPackCount >= StackCount) { _isDone = true; Logger.Log("Have stack count of {0} items in backpack", backPackCount); return(true); } } Logger.Debug("No Action Taken (StackCount={0} backPackCount={1} GameBalanceId={2} ActorId={3} GreaterRiftKey={4}", StackCount, backPackCount, GameBalanceId, ActorId, GreaterRiftKey); return(true); }
public static async Task <bool> RecipeBotRunner() { if (!ZetaDia.IsInTown) { return(false); } // For Smith plans, move to blacksmith // Use Item if not already known if (HasSmithPlans && Forge != null && UIElements.SalvageWindow.IsVisible) { ZetaDia.Me.Inventory.UseItem(BackPackSmithPlans.FirstOrDefault().DynamicId); return(true); } // Open Blacksmith window if (HasSmithPlans && Forge != null && !UIElements.SalvageWindow.IsVisible) { if (Forge.Distance > 10f) { var moveResult = await CommonCoroutines.MoveAndStop(Forge.Position, 10f, "Forge Location"); if (moveResult == MoveResult.ReachedDestination) { return(false); } } else { Forge.Interact(); return(true); } } // Upgrade Blacksmith to max.. not sure if we can do that? // If already known: Move to Vendor // Sell Item // For Jeweler plans // Move to Jeweler // Open Window // Upgrade Jeweler to max // Use Item if not already known // If already Known: move to vendor // Sell Item if (await MoveToAndOpenStash()) { return(true); } // Couldn't move to stash, something derpd? if (Stash == null) { return(false); } // Transfer Plans to backpack until pack full while (UIElements.StashWindow.IsVisible && TrinityItemManager.FindValidBackpackLocation(false) != TrinityItemManager.NoFreeSlot) { ZetaDia.Me.Inventory.QuickWithdraw(FirstStashPlan); } return(false); }