public static bool ProductStop() { try { Fsm.StopEngine(); if (_instanceFromOtherAssembly != null) { EventsListener.UnHookEvent(WoWEventsType.LOOT_READY, callback => FarmingTask.TakeFarmingLoots()); EventsListener.UnHookEvent(WoWEventsType.LOOT_OPENED, callback => FarmingTask.TakeFarmingLoots()); EventsListener.UnHookEvent(WoWEventsType.CINEMATIC_START, callback => ToggleCinematic(true)); EventsListener.UnHookEvent(WoWEventsType.CINEMATIC_STOP, callback => ToggleCinematic(false)); _instanceFromOtherAssembly.Stop(); Thread.Sleep(500); MovementManager.StopMove(); Fight.StopFight(); CombatClass.DisposeCombatClass(); LongMove.StopLongMove(); Memory.WowMemory.GameFrameUnLock(); return(true); } } catch (Exception e) { Logging.WriteError("ProductStop(): " + e); } return(false); }
public override void Run() { if (!Products.IsStarted || ObjectManager.Me.IsDeadMe || ObjectManager.Me.InCombatBlizzard) { return; } if (!FisherbotSetting.CurrentSetting.FishSchool) { if (_firstRun && FishingTask.IsLaunched) { _firstRun = false; } // If we have a saved position and we don't fish, then go to position if (FisherbotSetting.CurrentSetting.FisherbotPosition.IsValid && (!FishingTask.IsLaunched || _beenFighting) && !_firstRun) { _beenFighting = false; if (ObjectManager.Me.Position.DistanceTo(FisherbotSetting.CurrentSetting.FisherbotPosition) > 5) { LongMove.LongMoveGo(FisherbotSetting.CurrentSetting.FisherbotPosition); } else if (ObjectManager.Me.Position.DistanceTo(FisherbotSetting.CurrentSetting.FisherbotPosition) > 1.5f) { MovementManager.MoveTo(FisherbotSetting.CurrentSetting.FisherbotPosition); } MovementManager.Face(FisherbotSetting.CurrentSetting.FisherbotRotation); } // If we don't fish or the timer is null, then start a new timer, save position and fish if (timer == null || !FishingTask.IsLaunched) { timer = new nManager.Helpful.Timer(10 * 60 * 1000 + 10 * 1000); FisherbotSetting.CurrentSetting.FisherbotPosition = ObjectManager.Me.Position; FisherbotSetting.CurrentSetting.FisherbotRotation = ObjectManager.Me.Rotation; Fishing.EquipFishingPoles(FisherbotSetting.CurrentSetting.FishingPoleName); FishingTask.LoopFish(0, FisherbotSetting.CurrentSetting.UseLure, FisherbotSetting.CurrentSetting.LureName, FisherbotSetting.CurrentSetting.FishingPoleName, false, FisherbotSetting.AutomaticallyUseDraenorSecondaryBait); } // If the timer ended, stop fishing, equip weapon, null the timer else if (timer.IsReady) { FishingTask.StopLoopFish(); ItemsManager.EquipItemByName(FisherbotSetting.CurrentSetting.WeaponName); if (!string.IsNullOrEmpty(FisherbotSetting.CurrentSetting.ShieldName)) { ItemsManager.EquipItemByName(FisherbotSetting.CurrentSetting.ShieldName); } timer = null; } // We are in timer, we fish, then save the position else { if (FishingTask._lastSuccessfullFishing > Environment.TickCount - 5000) { FisherbotSetting.CurrentSetting.FisherbotPosition = ObjectManager.Me.Position; FisherbotSetting.CurrentSetting.FisherbotRotation = ObjectManager.Me.Rotation; // We successfully fished in the last 5 seconds, let's record our position again. } if (FishingTask._lastSuccessfullFishing != 0 && FishingTask._lastSuccessfullFishing < Environment.TickCount - 25000) { // We did not catch a single thing in the last 25 seconds... FishingTask.StopLoopFish(); return; } // _lastSuccessfullFishing is fine or we never fished yet, let it load :) Thread.Sleep(500); } // No more while, we test what we need and return return; } // Nodes fishing code if (_node.IsValid) { FisherbotSetting.CurrentSetting.FisherbotPosition = Bot.Profile.Points[Math.NearestPointOfListPoints(Bot.Profile.Points, _node.Position)]; Logging.Write("Fish " + _node.Name + " > " + _node.Position); } if (FisherbotSetting.CurrentSetting.FishSchool) { Point whereToGo = Fishing.FindTheUltimatePoint(_node.Position); if (whereToGo.Type == "invalid") { Logging.Write("No valid point found"); nManagerSetting.AddBlackList(_node.Guid); return; } bool r; List <Point> points = PathFinder.FindPath(whereToGo, out r); if (points.Count <= 1 || points.Count >= 20) { points.Clear(); points.Add(ObjectManager.Me.Position); points.Add(whereToGo); } else { for (int i = 0; i < points.Count; i++) { if (points[i].Z < whereToGo.Z) { points[i].Z = whereToGo.Z; } } } Logging.Write("Going to point > " + whereToGo.X + " ; " + whereToGo.Y + " ; " + whereToGo.Z + " ; " + points[0].Type); MovementManager.Go(points); timer = new nManager.Helpful.Timer(((int)Math.DistanceListPoint(points) / 3 * 1000) + 4000); while ((_node.IsValid || !FisherbotSetting.CurrentSetting.FishSchool) && Products.IsStarted && !ObjectManager.Me.IsDeadMe && !ObjectManager.Me.InInevitableCombat && !timer.IsReady && MovementManager.InMovement) { if (ObjectManager.Me.Position.DistanceTo2D(whereToGo) <= 0.2f) { MovementManager.StopMove(); break; } Thread.Sleep(50); } if (timer.IsReady && _node.GetDistance2D > DistanceMax) { Logging.Write("Fishing failed - No nearby point found (distance near position = " + ObjectManager.Me.Position.DistanceTo2D( FisherbotSetting.CurrentSetting.FisherbotPosition).ToString(CultureInfo.InvariantCulture) + ")"); MovementManager.StopMove(); nManagerSetting.AddBlackList(_node.Guid); return; } } // Stop move MovementManager.StopMove(); MountTask.DismountMount(); // Face if (_node.IsValid) { MovementManager.Face(_node); } else { MovementManager.Face(FisherbotSetting.CurrentSetting.FisherbotRotation); } // Ce met a la bonne distance du banc de poisson if (_node.IsValid) { int nbIsSwimming = 0; timer = new nManager.Helpful.Timer(1000 * 8); while ((Usefuls.IsSwimming || _node.GetDistance > DistanceMax || _node.GetDistance < DistanceMin) && Products.IsStarted && !ObjectManager.Me.IsDeadMe && !ObjectManager.Me.InCombat && !timer.IsReady) { if (nbIsSwimming * 100 > TimeTryFindGoodPos) { FishingTask.StopLoopFish(); MovementsAction.MoveBackward(false); MovementsAction.MoveForward(false); Logging.Write("BlackList " + _node.Name); nManagerSetting.AddBlackList(_node.Guid); return; } FishingTask.StopLoopFish(); MovementManager.Face(_node); if (Usefuls.IsSwimming || _node.GetDistance < DistanceMin) { MovementsAction.MoveForward(false); MovementsAction.MoveBackward(true); } if (_node.GetDistance > DistanceMax) { MovementsAction.MoveBackward(false); MovementsAction.MoveForward(true); } nbIsSwimming++; Thread.Sleep(100); } MovementsAction.MoveBackward(false); MovementsAction.MoveForward(false); if (timer.IsReady) { Logging.Write("Fishing failed - Out of range" + timer.IsReady.ToString()); MovementManager.StopMove(); nManagerSetting.AddBlackList(_node.Guid); return; } } // Fish Fishing.EquipFishingPoles(FisherbotSetting.CurrentSetting.FishingPoleName); FishingTask.LoopFish(_node.Guid, FisherbotSetting.CurrentSetting.UseLure, FisherbotSetting.CurrentSetting.LureName, FisherbotSetting.CurrentSetting.FishingPoleName, FisherbotSetting.CurrentSetting.PrecisionMode, FisherbotSetting.AutomaticallyUseDraenorSecondaryBait); timer = new nManager.Helpful.Timer(2 * 60 * 1000); while ((_node.IsValid || !FisherbotSetting.CurrentSetting.FishSchool) && Products.IsStarted && !ObjectManager.Me.IsDeadMe && !ObjectManager.Me.InCombat && !timer.IsReady && FishingTask.IsLaunched) { if (ObjectManager.Me.Position.DistanceTo2D(FisherbotSetting.CurrentSetting.FisherbotPosition) > 3.5f && !FisherbotSetting.CurrentSetting.FishSchool) { break; } Thread.Sleep(300); } FishingTask.StopLoopFish(); ItemsManager.EquipItemByName(FisherbotSetting.CurrentSetting.WeaponName); if (!string.IsNullOrEmpty(FisherbotSetting.CurrentSetting.ShieldName)) { ItemsManager.EquipItemByName(FisherbotSetting.CurrentSetting.ShieldName); } }
public override void Run() { try { if (MovementManager.InMovement) { return; } // Get if this zone is last zone if (LastZone != digsitesZone.id) { _nbTryFarmInThisZone = 0; // Reset nb try farm if zone is not last zone } LastZone = digsitesZone.id; // Set lastzone // Solving Every X Min if (timerAutoSolving == null) { timerAutoSolving = new Timer(SolvingEveryXMin * 1000 * 60); } if (timerAutoSolving.IsReady && !ObjectManager.ObjectManager.Me.IsDeadMe && !ObjectManager.ObjectManager.Me.InCombat) { MovementManager.StopMove(); LongMove.StopLongMove(); if (Archaeology.SolveAllArtifact(UseKeystones) > 0) { if (CrateRestored) { Archaeology.CrateRestoredArtifact(); } } timerAutoSolving = new Timer(SolvingEveryXMin * 1000 * 60); } if (MovementManager.InMovement) { return; } // Loop farm in zone // We must check Me.IsIndoor because no archeology is indoor int nbStuck = 0; // Nb of stuck direct try { if (myState != LocState.LocalMove) { MountTask.DismountMount(); } ObjectManager.WoWGameObject t = ObjectManager.ObjectManager.GetNearestWoWGameObject( ObjectManager.ObjectManager.GetWoWGameObjectByEntry(Archaeology.ArchaeologyItemsFindList)); if (t.IsValid) // If found then loot { nbCastSurveyError = 0; _lastGreenPosition = new Point(); _AntiPingPong = false; _greenCount = 0; if (myState == LocState.Looting) { if (timerLooting != null && timerLooting.IsReady) { MovementsAction.Jump(); Thread.Sleep(1500); } else { return; } } bool ValidPath; List <Point> points = PathFinder.FindPath(t.Position, out ValidPath, false); if (!ValidPath) { points.Add(t.Position); } MovementManager.Go(points); if (nbLootAttempt > 2) { MovementManager.StopMove(); LongMove.StopLongMove(); if (Archaeology.SolveAllArtifact(UseKeystones) == 0) { nManagerSetting.AddBlackList(t.Guid); // bugged artifacts not lootable Logging.Write("Black-listing bugged artifact"); } else if (CrateRestored) { Archaeology.CrateRestoredArtifact(); } nbLootAttempt = 0; return; } Logging.Write("Loot " + t.Name); Timer timer = new Timer(1000 * Math.DistanceListPoint(points) / 3); while (MovementManager.InMovement && !timer.IsReady && t.GetDistance > 3.5f) { Thread.Sleep(100); if (ObjectManager.ObjectManager.Me.InInevitableCombat || ObjectManager.ObjectManager.Me.IsDeadMe) { return; } } MovementManager.StopMove(); // avoid a red wow error Thread.Sleep(150); Interact.InteractWith(t.GetBaseAddress); while (ObjectManager.ObjectManager.Me.IsCast) { Thread.Sleep(100); } if (ObjectManager.ObjectManager.Me.InCombat) { return; } Statistics.Farms++; nbLootAttempt++; myState = LocState.Looting; if (timerLooting == null) { timerLooting = new Timer(1000 * 5); } else { timerLooting.Reset(); } return; } if (_nbTryFarmInThisZone > MaxTryByDigsite) // If try > config try black list { nbLootAttempt = 0; BlackListDigsites.Add(digsitesZone.id); Logging.Write("Black List Digsite: " + digsitesZone.name); myState = LocState.LocalMove; nbCastSurveyError = 0; return; } bool moreMovementNeeded = false; if (qPOI != null && !qPOI.ValidPoint && qPOI.Center.DistanceTo2D(ObjectManager.ObjectManager.Me.Position) < 40.0f) { #pragma warning disable 168 // We call qPOI.MiddlePoint to make the WoWQuestPOIPoint instance compute the middle point, but I don't care were it is Point p = qPOI.MiddlePoint; // we are near enough to compute it #pragma warning restore 168 if (Usefuls.IsFlying) { moreMovementNeeded = true; MovementManager.StopMove(); } } // Go To Zone if (qPOI != null && (moreMovementNeeded || !qPOI.IsInside(ObjectManager.ObjectManager.Me.Position))) { if (MountTask.GetMountCapacity() == MountCapacity.Feet || MountTask.GetMountCapacity() == MountCapacity.Ground) { int LodestoneID = 117389; if (!_travelDisabled && ItemsManager.GetItemCount(LodestoneID) > 0 && Usefuls.RealContinentId == 1116 && qPOI.Center.DistanceTo2D(ObjectManager.ObjectManager.Me.Position) > 3000f) { ObjectManager.WoWItem item = ObjectManager.ObjectManager.GetWoWItemById(LodestoneID); if (item != null && item.IsValid && !ItemsManager.IsItemOnCooldown(LodestoneID) && ItemsManager.IsItemUsable(LodestoneID)) { Logging.Write("Using a Draenor Archaeologist's Lodestone"); Products.Products.InManualPause = true; // Prevent triggering "Player teleported" ItemsManager.UseItem(LodestoneID); Thread.Sleep(3000 + Usefuls.Latency); digsitesZone = new Digsite(); // Reset the choice made return; } } Logging.Write("Not inside, then go to Digsite " + digsitesZone.name); Point me = ObjectManager.ObjectManager.Me.Position; if (_travelLocation != null && _travelLocation.DistanceTo(me) > 0.1f) { if (Products.Products.TravelRegenerated && Products.Products.TravelFrom.IsValid) { _travelLocation = Products.Products.TravelFrom; Products.Products.TravelRegenerated = false; } } if ((_travelLocation == null || _travelLocation.DistanceTo(me) > 0.1f) && !_travelDisabled && !Usefuls.IsFlying) { MovementManager.StopMove(); Logging.Write("Calling travel system to go to digsite " + digsitesZone.name + " (" + digsitesZone.id + ")..."); Products.Products.TravelToContinentId = Usefuls.ContinentId; Products.Products.TravelTo = qPOI.Center; Products.Products.TravelFromContinentId = Usefuls.ContinentId; Products.Products.TravelFrom = me; // Pass the check for valid destination as a lambda Products.Products.TargetValidationFct = qPOI.IsInside; _travelLocation = Products.Products.TravelFrom; return; } if (_travelLocation.DistanceTo(me) <= 0.1f) { _travelDisabled = true; } List <Point> newPath; newPath = PathFinder.FindPath(qPOI.Center); MovementManager.Go(newPath); } else if (qPOI.ValidPoint) { if (moreMovementNeeded || !qPOI.IsInside(ObjectManager.ObjectManager.Me.Position)) { Point destination = new Point(qPOI.MiddlePoint); destination.Type = "flying"; if (moreMovementNeeded) { Logging.Write("Landing on the digsite"); } else { Logging.Write("Not inside, then go to Digsite " + digsitesZone.name + "; X: " + destination.X + "; Y: " + destination.Y + "; Z: " + (int)destination.Z); } MovementManager.Go(new List <Point>(new[] { destination })); // MoveTo Digsite } } else { // here we need to go to center, THEN compute middle point Point destination = qPOI.Center; destination.Z += 40.0f; destination.Type = "flying"; Logging.Write("Go to Digsite " + digsitesZone.name + "; X: " + destination.X + "; Y: " + destination.Y + "; Z: " + (int)destination.Z); MovementManager.Go(new List <Point>(new[] { destination })); // MoveTo Digsite } myState = LocState.LocalMove; return; } // Find loot with Survey nbLootAttempt = 0; t = ObjectManager.ObjectManager.GetNearestWoWGameObject( ObjectManager.ObjectManager.GetWoWGameObjectByDisplayId(Archaeology.SurveyList)); if (t.GetBaseAddress == 0 || myState == LocState.GoingNextPoint || // recast if we moved even if last is still spawned myState == LocState.Looting) // after we looted we need to recast survey spell, even if the previous one is still spawned { if (!Archaeology.DigsiteZoneIsAvailable(digsitesZone)) { return; } if (myState == LocState.LocalMove) { MountTask.DismountMount(); } surveySpell.Launch(); myState = LocState.Survey; if (ObjectManager.ObjectManager.Me.InCombat) { return; } Thread.Sleep(1750 + Usefuls.Latency); // let's wait a fair bit nbCastSurveyError++; if (nbCastSurveyError > 3) { if (ObjectManager.ObjectManager.Me.Position.DistanceTo2D(qPOI.MiddlePoint) < 5) { // This means we are in a wrong digsite List <Digsite> listDigsitesZone; if (!_inSecondDigSiteWithSameName) { listDigsitesZone = Archaeology.GetDigsitesZoneAvailable(t.Name); } else // very very rare case I had: back to the first digsite with same name after the 2nd one { listDigsitesZone = Archaeology.GetDigsitesZoneAvailable(); } foreach (Digsite dg in listDigsitesZone) { if (dg.name == t.Name) { digsitesZone = dg; } } WoWResearchSite OneSite; if (!_inSecondDigSiteWithSameName) { OneSite = WoWResearchSite.FromName(digsitesZone.name, true); } else { OneSite = WoWResearchSite.FromName(digsitesZone.name, false); } qPOI = WoWQuestPOIPoint.FromSetId(OneSite.Record.QuestIdPoint); _inSecondDigSiteWithSameName = !_inSecondDigSiteWithSameName; nbCastSurveyError = 0; return; } if (MountTask.GetMountCapacity() == MountCapacity.Feet || MountTask.GetMountCapacity() == MountCapacity.Ground) { Logging.Write("Too many errors, then go to Digsite " + digsitesZone.name); List <Point> newPath = PathFinder.FindPath(qPOI.Center); MovementManager.Go(newPath); } else { if (qPOI != null) { Point destination = qPOI.MiddlePoint; Logging.Write("Too many errors, then go to Digsite " + digsitesZone.name + "; X: " + destination.X + "; Y: " + destination.Y + "; Z: " + (int)destination.Z); MovementManager.Go(new List <Point>(new[] { destination })); // MoveTo Digsite } } nbCastSurveyError = 0; return; } _nbTryFarmInThisZone++; return; } if (myState == LocState.GoingNextPoint) { return; } nbCastSurveyError = 0; // Reset try cast survey if ((ObjectManager.ObjectManager.Me.InCombat && !(ObjectManager.ObjectManager.Me.IsMounted && (nManagerSetting.CurrentSetting.IgnoreFightIfMounted || Usefuls.IsFlying)))) { return; } Point p0; float angle; { Point p; float distance, distanceMin, distanceMax, decrement, increment; if (t.DisplayId == 10103) // Survey Tool (Red) 100 yard { distance = 90f; distanceMin = 20f; distanceMax = 210f; increment = 8f; decrement = 8f; _lastGreenPosition = new Point(); _AntiPingPong = false; _greenCount = 0; } else if (t.DisplayId == 10102) // Survey Tool (Yellow) 50 yard { distance = 46f; distanceMin = 20f; distanceMax = 60f; increment = 7f; decrement = 6.5f; _lastGreenPosition = new Point(); _AntiPingPong = false; _greenCount = 0; } else // Survey Tool (Green) 25 yard (t.DisplayId == 10101) { _greenCount++; increment = 4f; if (_greenCount >= 10) { _greenCount = 0; _lastGreenPosition = new Point(); Point destination = qPOI.MiddlePoint; _AntiPingPong = false; Logging.Write("Stuck, then go to Digsite " + digsitesZone.name + "; X: " + destination.X + "; Y: " + destination.Y + "; Z: " + (int)destination.Z); MountTask.Mount(true, true); MovementManager.Go(new List <Point>(new[] { destination })); // MoveTo Digsite return; } if (_AntiPingPong) { Logging.Write("Ping-pong detected, shortening the distance"); distance = 11f; distanceMin = 6f; distanceMax = 16f; decrement = 4f; } else { distance = 19f; distanceMin = 7f; distanceMax = 41f; decrement = 3f; } } { float d = distance; p0 = new Point(t.Position); angle = t.Orientation; p = Math.GetPosition2DOfAngleAndDistance(p0, angle, d); p.Z = PathFinder.GetZPosition(p, true); bool valid; PathFinder.FindPath(p, out valid); if (qPOI != null) { bool IamOutOfWater = IsPointOutOfWater(ObjectManager.ObjectManager.Me.Position); while (!valid || p.Z == 0 || !qPOI.IsInside(p) || !(!IamOutOfWater || IsPointOutOfWater(p))) { if (d + increment > distanceMax) { break; } d += increment; Point newone = Math.GetPosition2DOfAngleAndDistance(p0, angle, d); if (qPOI.IsInside(newone)) { p = new Point(newone); p.Z += d / 10.0f; // just so that GetZ don't find caves too easiely p.Z = PathFinder.GetZPosition(p, true); if (p.Z == 0) // if p == 0 we don't care about the path { valid = false; } else if (Math.DistanceListPoint(PathFinder.FindLocalPath(p, out valid)) > d * 4 && d > 30) { valid = false; } } // Since these direction are approximate, also search in a pi/5 angle if (!valid /* && t.DisplayId == 10103*/) { float angleplus = Math.FixAngle(angle + ((float)System.Math.PI / 10f)); newone = Math.GetPosition2DOfAngleAndDistance(p0, angleplus, d); p = new Point(newone); p.Z += d / 10.0f; // just so that GetZ don't find caves too easiely p.Z = PathFinder.GetZPosition(p, true); if (p.Z == 0) // if p == 0 we don't care about the path { valid = false; } else if (Math.DistanceListPoint(PathFinder.FindLocalPath(p, out valid)) > d * 4 && d > 30) { valid = false; } if (valid) { Logging.Write("Angles+ for distance " + d); } } if (!valid /* && t.DisplayId == 10103*/) { float angleminus = Math.FixAngle(angle - ((float)System.Math.PI / 10f)); newone = Math.GetPosition2DOfAngleAndDistance(p0, angleminus, d); p = new Point(newone); p.Z += d / 10.0f; // just so that GetZ don't find caves too easiely p.Z = PathFinder.GetZPosition(p, true); if (p.Z == 0) // if p == 0 we don't care about the path { valid = false; } else if (Math.DistanceListPoint(PathFinder.FindLocalPath(p, out valid)) > d * 4 && d > 30) { valid = false; } if (valid) { Logging.Write("Angles- for distance " + d); } } } if (!valid || p.Z == 0 || !qPOI.IsInside(p) || !(!IamOutOfWater || IsPointOutOfWater(p))) { d = distance; while (!valid || p.Z == 0 || !qPOI.IsInside(p) || !(!IamOutOfWater || IsPointOutOfWater(p))) { if (d - decrement < distanceMin) { break; } d -= decrement; Point newone = Math.GetPosition2DOfAngleAndDistance(p0, angle, d); if (qPOI.IsInside(newone)) { p = new Point(newone); p.Z += d / 10.0f; // just so that the the GetZ don't find caves too easiely p.Z = PathFinder.GetZPosition(p, true); if (p.Z == 0) // if p == 0 we don't care about the path { valid = false; } else if (Math.DistanceListPoint(PathFinder.FindLocalPath(p, out valid)) > d * 4 && d > 30) { valid = false; } } // Since these direction are approximate, also search in a pi/5 angle if (!valid /* && t.DisplayId == 10103*/) { float angleplus = Math.FixAngle(angle + ((float)System.Math.PI / 10f)); newone = Math.GetPosition2DOfAngleAndDistance(p0, angleplus, d); p = new Point(newone); p.Z += d / 10.0f; // just so that GetZ don't find caves too easiely p.Z = PathFinder.GetZPosition(p, true); if (p.Z == 0) // if p == 0 we don't care about the path { valid = false; } else if (Math.DistanceListPoint(PathFinder.FindLocalPath(p, out valid)) > d * 4 && d > 30) { valid = false; } if (valid) { Logging.Write("Angles+ for distance " + d); } } if (!valid /* && t.DisplayId == 10103*/) { float angleminus = Math.FixAngle(angle - ((float)System.Math.PI / 10f)); newone = Math.GetPosition2DOfAngleAndDistance(p0, angleminus, d); p = new Point(newone); p.Z += d / 10.0f; // just so that GetZ don't find caves too easiely p.Z = PathFinder.GetZPosition(p, true); if (p.Z == 0) // if p == 0 we don't care about the path { valid = false; } else if (Math.DistanceListPoint(PathFinder.FindLocalPath(p, out valid)) > d * 4 && d > 30) { valid = false; } if (valid) { Logging.Write("Angles- for distance " + d); } } } } } // check pingpong but not a second time if (_AntiPingPong) { _AntiPingPong = false; } else if (t.DisplayId == 10101 && _lastGreenPosition.IsValid && p.DistanceTo2D(_lastGreenPosition) <= 7f) { _AntiPingPong = true; } // then remmember the last Green Position if (t.DisplayId == 10101) { _lastGreenPosition = new Point(ObjectManager.ObjectManager.Me.Position); } if (_AntiPingPong) { myState = LocState.LocalMove; return; } Logging.Write("Distance " + d + " selected"); } myState = LocState.GoingNextPoint; // Find Path bool resultB; List <Point> points = PathFinder.FindLocalPath(p, out resultB, false); // If path not found find nearer if (points.Count <= 0) { Point pt = Math.GetPosition2DOfAngleAndDistance(p0, angle, 15); pt.Z = ObjectManager.ObjectManager.Me.Position.Z; points = PathFinder.FindLocalPath(pt, out resultB, false); if (points.Count > 0 && resultB) { p = new Point(pt); } } // Go to next position if ((!resultB && p.DistanceTo(ObjectManager.ObjectManager.Me.Position) > 10) || nbStuck >= 2) // Use fly mount { p.Z = PathFinder.GetZPosition(p); if (p.Z == 0) { p.Z = ObjectManager.ObjectManager.Me.Position.Z + 35; } else { p.Z = p.Z + 5.0f; } if ((ObjectManager.ObjectManager.Me.InCombat && !(ObjectManager.ObjectManager.Me.IsMounted && (nManagerSetting.CurrentSetting.IgnoreFightIfMounted || Usefuls.IsFlying)))) { return; } MountTask.Mount(true, true); LongMove.LongMoveByNewThread(p); Timer timer = new Timer(2000 * points[points.Count - 1].DistanceTo(ObjectManager.ObjectManager.Me.Position) / 3); while (LongMove.IsLongMove && !timer.IsReady && ObjectManager.ObjectManager.Me.Position.DistanceTo2D(p) > 0.5f) { if ((ObjectManager.ObjectManager.Me.InCombat && !(ObjectManager.ObjectManager.Me.IsMounted && (nManagerSetting.CurrentSetting.IgnoreFightIfMounted || Usefuls.IsFlying)))) { LongMove.StopLongMove(); return; } Thread.Sleep(100); } LongMove.StopLongMove(); while (MovementManager.IsUnStuck) { if (ObjectManager.ObjectManager.Me.IsDeadMe) { return; } Thread.Sleep(100); LongMove.StopLongMove(); } MovementManager.StopMove(); MountTask.DismountMount(); // ReSharper disable RedundantAssignment nbStuck = 0; // ReSharper restore RedundantAssignment } else // walk to next position { float d1 = Math.DistanceListPoint(points); float d2 = points[0].DistanceTo(points[points.Count - 1]); // here we will try to shortcut the path using a fly mount if (MountTask.GetMountCapacity() == MountCapacity.Fly && d1 > 80 && d1 > (d2 * 2)) { Point startpoint = new Point(ObjectManager.ObjectManager.Me.Position); Point endpoint = new Point(points[points.Count - 1]); float z1 = startpoint.Z; float z2 = endpoint.Z; float zref = System.Math.Max(z1, z2) + 6.0f; Point pref1 = new Point(startpoint); pref1.Z = zref; Point pref2 = new Point(endpoint); pref2.Z = zref; bool badres = TraceLine.TraceLineGo(startpoint, pref1) || TraceLine.TraceLineGo(pref1, pref2) || TraceLine.TraceLineGo(pref2, endpoint); if (!badres) { Logging.Write("Flying to shortcut the path"); MountTask.Mount(true, true); if (Usefuls.IsFlying) // Failsafe: in case we are indoor don't try { points = new List <Point>(); pref1.Z += 2f; pref2.Z += 2f; points.Add(pref1); points.Add(pref2); points.Add(endpoint); } } } if (d1 > nManagerSetting.CurrentSetting.MinimumDistanceToUseMount && !nManagerSetting.CurrentSetting.UseGroundMount) { MountTask.Mount(); } if (Usefuls.IsFlying) { for (int i = 0; i < points.Count; i++) { points[i].Type = "flying"; } } MovementManager.Go(points); float d = Math.DistanceListPoint(points) / 3; if (d > 200) { d = 200; } float tm_t = 1000 * d / 2 + 1500; if (Usefuls.IsSwimming) { tm_t /= 0.6f; } Timer timer = new Timer(tm_t); while (MovementManager.InMovement && !timer.IsReady && ObjectManager.ObjectManager.Me.Position.DistanceTo2D(p) > 0.5f) { if ((ObjectManager.ObjectManager.Me.InCombat && !(ObjectManager.ObjectManager.Me.IsMounted && (nManagerSetting.CurrentSetting.IgnoreFightIfMounted || Usefuls.IsFlying)))) { return; } Thread.Sleep(100); } // incremente nbstuck if player is stuck if (ObjectManager.ObjectManager.Me.Position.DistanceTo(t.Position) < 5 || (MovementManager.InMovement && !ObjectManager.ObjectManager.Me.InInevitableCombat && timer.IsReady)) { // ReSharper disable RedundantAssignment nbStuck++; } // ReSharper restore RedundantAssignment else { // ReSharper disable RedundantAssignment nbStuck = 0; } // ReSharper restore RedundantAssignment if (ObjectManager.ObjectManager.Me.InInevitableCombat) { return; } MovementManager.StopMove(); while (MovementManager.IsUnStuck) { if (ObjectManager.ObjectManager.Me.IsDeadMe) { return; } Thread.Sleep(100); MovementManager.StopMove(); } } } } catch { } } catch { } }
public override void Run() { MovementManager.StopMove(); MovementManager.StopMoveTo(); if (ObjectManager.Me.HaveBuff(ResurrectionSicknessId)) { Logging.Write("Resurrection Sickness detected, we will now wait its full duration to avoid dying in chain."); while (ObjectManager.Me.HaveBuff(ResurrectionSicknessId)) { Thread.Sleep(1000); // We don't need to return if we get in combat, we would die quickly anyway, and we will ressurect from our body this time. } return; } Logging.Write("The player has died. Starting the resurrection process."); #region Reincarnation if (ObjectManager.Me.WowClass == WoWClass.Shaman && _shamanReincarnation.KnownSpell && _shamanReincarnation.IsSpellUsable) { Thread.Sleep(3500); // Let our killers reset. Lua.RunMacroText("/click StaticPopup1Button2"); Thread.Sleep(1000); if (!ObjectManager.Me.IsDeadMe) { _failed = false; Logging.Write("The player have been resurrected using Shaman Reincarnation."); Statistics.Deaths++; return; } } #endregion #region Soulstone if (ObjectManager.Me.WowClass == WoWClass.Warlock && _warlockSoulstone.KnownSpell && _warlockSoulstone.HaveBuff || ObjectManager.Me.HaveBuff(6203)) { Thread.Sleep(3500); // Let our killers reset. Lua.RunMacroText("/click StaticPopup1Button2"); Thread.Sleep(1000); if (!ObjectManager.Me.IsDeadMe) { _failed = false; Logging.Write(ObjectManager.Me.WowClass == WoWClass.Warlock ? "The player have been resurrected using his Soulstone." : "The player have been resurrected using a Soulstone offered by a Warlock."); Statistics.Deaths++; return; } } #endregion Interact.Repop(); Thread.Sleep(1000); while (!ObjectManager.Me.PositionCorpse.IsValid && ObjectManager.Me.Health <= 0 && Products.Products.IsStarted && Usefuls.InGame) { Interact.Repop(); Thread.Sleep(1000); } Thread.Sleep(1000); #region Battleground resurrection if (Usefuls.IsInBattleground) { _battlegroundResurrect = new Timer(1000 * 35); while (Usefuls.IsLoading && Products.Products.IsStarted && Usefuls.InGame) { Thread.Sleep(100); } Thread.Sleep(4000); /*var factionBattlegroundSpiritHealer = * new WoWUnit( * ObjectManager.GetNearestWoWUnit( * ObjectManager.GetWoWUnitByName(ObjectManager.Me.PlayerFaction + * " Spirit Guide")).GetBaseAddress); * if (!factionBattlegroundSpiritHealer.IsValid) * { * Logging.Write("Faction Spirit Healer not found, teleport back to the cimetery."); * Interact.TeleportToSpiritHealer(); * Thread.Sleep(5000); * } * else * { * if (factionBattlegroundSpiritHealer.GetDistance > 25) * { * Interact.TeleportToSpiritHealer(); * Thread.Sleep(5000); * }*/ while (ObjectManager.Me.IsDeadMe) { if (_battlegroundResurrect.IsReady) { Interact.TeleportToSpiritHealer(); _battlegroundResurrect = new Timer(1000 * 35); Logging.Write("The player have not been resurrected by any Battleground Spirit Healer in a reasonable time, Teleport back to the cimetary."); Thread.Sleep(5000); } Thread.Sleep(1000); } _failed = false; Logging.Write("The player have been resurrected by the Battleground Spirit Healer."); Statistics.Deaths++; return; /*}*/ } #endregion #region Go To Corpse resurrection if (ObjectManager.Me.Level <= 10) { _forceSpiritHealer = true; Logging.Write("We have no penalty for using Spirit Healer, so let's use it."); } else if (ObjectManager.Me.PositionCorpse.IsValid && !nManagerSetting.CurrentSetting.UseSpiritHealer && !_forceSpiritHealer) { while (Usefuls.IsLoading && Products.Products.IsStarted && Usefuls.InGame) { Thread.Sleep(100); } Thread.Sleep(1000); Point tPointCorps; if (ObjectManager.Me.IsMounted || MountTask.OnFlyMount()) { MountTask.Takeoff(); tPointCorps = ObjectManager.Me.PositionCorpse; tPointCorps.Z = tPointCorps.Z + 15; LongMove.LongMoveByNewThread(tPointCorps); } else { tPointCorps = ObjectManager.Me.PositionCorpse; bool success; tPointCorps.Z = PathFinder.GetZPosition(tPointCorps); // make sure to get the right Z in case we died in the air/surface of water. List <Point> points = PathFinder.FindPath(tPointCorps, out success); if (!success) { _forceSpiritHealer = true; Logging.Write("There in no easy acces to the corpse, use Spirit Healer instead."); // todo: Check few positions "In Range", we don't necesserly need to get to our body. return; } if (points.Count > 1 || (points.Count <= 1 && !nManagerSetting.CurrentSetting.UseSpiritHealer)) { MovementManager.Go(points); } } while ((MovementManager.InMovement || LongMove.IsLongMove) && Products.Products.IsStarted && Usefuls.InGame && ObjectManager.Me.IsDeadMe) { if ((tPointCorps.DistanceTo(ObjectManager.Me.Position) < 25 && !_failed) || (Memory.WowMemory.Memory.ReadInt(Memory.WowProcess.WowModule + (uint)Addresses.Player.RetrieveCorpseWindow) > 0 && !_failed) || ObjectManager.Me.PositionCorpse.DistanceTo(ObjectManager.Me.Position) < 5) { LongMove.StopLongMove(); MovementManager.StopMove(); } Thread.Sleep(100); } if (Usefuls.IsFlying) { Tasks.MountTask.Land(); } if (Memory.WowMemory.Memory.ReadInt(Memory.WowProcess.WowModule + (uint)Addresses.Player.RetrieveCorpseWindow) <= 0) { _failed = true; } Point safeResPoint = Usefuls.GetSafeResPoint(); if (safeResPoint.IsValid && nManagerSetting.CurrentSetting.ActivateSafeResurrectionSystem) { MovementManager.StopMove(); bool success; List <Point> points = PathFinder.FindPath(safeResPoint, out success); if (!success) { return; } MovementManager.Go(points); Timer distanceTimer = null; while (safeResPoint.DistanceTo(ObjectManager.Me.Position) > 5) { if (!MovementManager.InMovement) { MovementManager.Go(points); } if (distanceTimer == null && tPointCorps.DistanceTo(ObjectManager.Me.Position) <= 39.0f) { distanceTimer = new Timer(10000); // start a 10sec timer when we are in range of our corpse. } if (distanceTimer != null && distanceTimer.IsReady) { break; // Sometimes we cannot join the desired destination because of a wall, or water level. } Thread.Sleep(1000); } MovementManager.StopMove(); while ((tPointCorps.DistanceTo(ObjectManager.Me.Position) <= 39.0f || Memory.WowMemory.Memory.ReadInt(Memory.WowProcess.WowModule + (uint)Addresses.Player.RetrieveCorpseWindow) > 0) && ObjectManager.Me.IsDeadMe && Products.Products.IsStarted && Usefuls.InGame) { Interact.RetrieveCorpse(); Thread.Sleep(1000); } } else { if (tPointCorps.DistanceTo(ObjectManager.Me.Position) <= 30.0f || Memory.WowMemory.Memory.ReadInt(Memory.WowProcess.WowModule + (uint)Addresses.Player.RetrieveCorpseWindow) > 0) { while ((tPointCorps.DistanceTo(ObjectManager.Me.Position) <= 30.0f || Memory.WowMemory.Memory.ReadInt(Memory.WowProcess.WowModule + (uint)Addresses.Player.RetrieveCorpseWindow) > 0) && ObjectManager.Me.IsDeadMe && Products.Products.IsStarted && Usefuls.InGame) { Interact.RetrieveCorpse(); Thread.Sleep(1000); } } } } if (!ObjectManager.Me.IsDeadMe) { _failed = false; Logging.Write("The player have been resurrected when retrieving his corpse."); Statistics.Deaths++; return; } #endregion GoToCorp #region Spirit Healer resurrection if (nManagerSetting.CurrentSetting.UseSpiritHealer || _forceSpiritHealer || ObjectManager.Me.HaveBuff(15007)) { Thread.Sleep(4000); WoWUnit objectSpiritHealer = new WoWUnit(ObjectManager.GetNearestWoWUnit(ObjectManager.GetWoWUnitSpiritHealer()).GetBaseAddress); int stuckTemps = 5; if (!objectSpiritHealer.IsValid) { Logging.Write("Spirit Healer not found, teleport back to the cimetery."); Interact.TeleportToSpiritHealer(); Thread.Sleep(5000); } else { if (objectSpiritHealer.GetDistance > 25) { Interact.TeleportToSpiritHealer(); Thread.Sleep(5000); } MovementManager.MoveTo(objectSpiritHealer.Position); while (objectSpiritHealer.GetDistance > 5 && Products.Products.IsStarted && stuckTemps >= 0 && Usefuls.InGame) { Thread.Sleep(300); if (!ObjectManager.Me.GetMove && objectSpiritHealer.GetDistance > 5) { MovementManager.MoveTo(objectSpiritHealer.Position); stuckTemps--; } } Interact.InteractWith(objectSpiritHealer.GetBaseAddress); Thread.Sleep(2000); Interact.SpiritHealerAccept(); Thread.Sleep(1000); if (!ObjectManager.Me.IsDeadMe) { _forceSpiritHealer = false; Logging.Write("The player have been resurrected by the Spirit Healer."); Statistics.Deaths++; } } } #endregion SpiritHealer }
public override void Run() { if (MovementManager.InMovement) { return; } // Now configure if not already done if (tList == null) { // Fill the task list tList = new Stack <Task>(); tList.Push(Task.CheckGarrisonRessourceCache); if (Garrison.GetGarrisonLevel() > 1) { tList.Push(Task.MineWorkOrder); tList.Push(Task.GatherMinerals); tList.Push(Task.GardenWorkOrder); tList.Push(Task.GatherHerbs); } tList.Push(Task.GoToGarrison); // And fill the variables _cacheGarrison = new List <int> { 237722, 236916, 237191, 237724, 237720, 237723 }; if (ObjMgr.Me.PlayerFaction == "Alliance") { _npcGarden = 85514; _cacheGarden = 235885; _npcMine = 77730; _cacheMine = 235886; _garden = new Point { X = 1833.85f, Y = 154.7408f, Z = 76.66339f }; _mineEntrance = new Point { X = 1886.021f, Y = 83.23455f, Z = 84.31888f }; _cacheGarrisonPoint = new Point { X = 1914.361f, Y = 290.3863f, Z = 88.96407f }; } else { _npcGarden = 85783; _cacheGarden = 239238; _npcMine = 81688; _cacheMine = 239237; _garden = new Point { X = 5413.795f, Y = 4548.928f, Z = 139.1232f }; _mineEntrance = new Point { X = 5465.796f, Y = 4430.045f, Z = 145.4595f }; _cacheGarrisonPoint = new Point { X = 5592.229f, Y = 4569.476f, Z = 136.1069f }; } _cacheGardenGathered = false; _cacheMineGathered = false; } bool success, display = false; Point me = ObjMgr.Me.Position; Task currentTask = tList.Peek(); if (currentTask != previousTask) { previousTask = currentTask; display = true; } switch (currentTask) { case Task.GoToGarrison: if (display) { Logging.Write("Task: go to garrison"); } /*var pathToGarrison2 = PathFinder.FindPath(new Point() { X = 2727.872f, Y = 6451.539f, Z = 191.9229f }, out success); * if (success) * { * //this code allow me to test a path easily. * MovementManager.Go(pathToGarrison2); * return; * }*/ if (!Garrison.GarrisonMapIdList.Contains(Usefuls.RealContinentId)) { // We are in Draenor if (Usefuls.ContinentId == Usefuls.ContinentIdByContinentName("Draenor")) { // We can fly, then fly if (MountTask.GetMountCapacity() == MountCapacity.Fly) { LongMove.LongMoveGo(_cacheGarrisonPoint); return; } // else if not too far go by foot else if (_cacheGarrisonPoint.DistanceTo(me) < 100) { List <Point> pathToGarrison = PathFinder.FindPath(_cacheGarrisonPoint, out success); if (success) { MovementManager.Go(pathToGarrison); return; } } } // We have to use the garrison hearthstone if (ItemsManager.GetItemCount(GarrisonHearthstone) > 0 && !ItemsManager.IsItemOnCooldown(GarrisonHearthstone)) { Logging.Write("Using garrison Hearthstone"); ItemsManager.UseItem(GarrisonHearthstone); } else { Logging.Write("Run aborted, you are not in Draenor or too far away and don't known how to fly and don't have a Garrison Hearthstone or it's on Cooldown."); tList.Clear(); break; // prevent poping an empty stack, break to the end } } tList.Pop(); break; case Task.CheckGarrisonRessourceCache: if (display) { Logging.Write("Task: gather garrison cache"); } if (_cacheGarrisonPoint.DistanceTo(me) > 75.0f) { List <Point> pathToGCache = PathFinder.FindPath(_cacheGarrisonPoint); MovementManager.Go(pathToGCache); return; } WoWGameObject cache = ObjMgr.GetNearestWoWGameObject(ObjMgr.GetWoWGameObjectById(_cacheGarrison)); if (cache.GetBaseAddress != 0) { if (cache.Position.DistanceTo(me) > 5.0f) { _targetNpc = new Npc { Entry = cache.Entry, Position = cache.Position }; MovementManager.FindTarget(ref _targetNpc, 5f); return; } Interact.InteractWith(cache.GetBaseAddress, true); } tList.Pop(); break; case Task.GatherHerbs: if (display) { Logging.Write("Task: gather plants in garrison garden"); } if (_garden.DistanceTo(me) > 15.0f) { List <Point> pathToGarden = PathFinder.FindPath(_garden, out success); // assume success MovementManager.Go(pathToGarden); return; } nManagerSetting.CurrentSetting.ActivateHerbsHarvesting = true; nManagerSetting.CurrentSetting.GatheringSearchRadius = 30f; if (!FarmingState.NeedToRun) // Nothing anymore to farm, then next task { Logging.Write("Finished to farm garrison garden"); nManagerSetting.CurrentSetting.ActivateHerbsHarvesting = false; tList.Pop(); } break; case Task.GatherMinerals: if (display) { Logging.Write("Task: gather ores and carts in garrison mine"); } if (_mineEntrance.DistanceTo(me) > 15.0f) { List <Point> pathToMine = PathFinder.FindPath(_mineEntrance, out success); // assume success MovementManager.Go(pathToMine); return; } nManagerSetting.CurrentSetting.GatheringSearchRadius = 120f; nManagerSetting.CurrentSetting.ActivateVeinsHarvesting = true; if (FarmingState.NeedToRun) { Logging.Write("Take coffee and Mining Pick buffs"); if (ItemsManager.GetItemCount(PreservedMiningPick) > 0 && !ItemsManager.IsItemOnCooldown(PreservedMiningPick) && ItemsManager.IsItemUsable(PreservedMiningPick) && !ObjMgr.Me.HaveBuff(PreservedMiningPickBuff)) { ItemsManager.UseItem(PreservedMiningPick); Thread.Sleep(150 + Usefuls.Latency); while (ObjMgr.Me.IsCast) { Thread.Sleep(150); } Thread.Sleep(1000); } if (ItemsManager.GetItemCount(MinerCoffee) > 0 && !ItemsManager.IsItemOnCooldown(MinerCoffee) && ItemsManager.IsItemUsable(MinerCoffee) && ObjMgr.Me.BuffStack(MinerCoffeeBuff) < 2) { ItemsManager.UseItem(MinerCoffee); Thread.Sleep(150 + Usefuls.Latency); while (ObjMgr.Me.IsCast) { Thread.Sleep(150); } } } else // Nothing anymore to farm, then next task { Logging.Write("Finished to farm garrison mine"); nManagerSetting.CurrentSetting.ActivateVeinsHarvesting = false; tList.Pop(); } break; case Task.GardenWorkOrder: if (display) { Logging.Write("Task: collect garden cache and send work order"); } if (!_cacheGardenGathered) { WoWGameObject gardenCache = ObjMgr.GetNearestWoWGameObject(ObjMgr.GetWoWGameObjectById(_cacheGarden)); if (gardenCache.GetBaseAddress != 0) { if (gardenCache.Position.DistanceTo(me) > 5.0f) { _targetNpc = new Npc { Entry = gardenCache.Entry, Position = gardenCache.Position }; MovementManager.FindTarget(ref _targetNpc, 5f); return; } else { Thread.Sleep(Usefuls.Latency + 250); Interact.InteractWith(gardenCache.GetBaseAddress, true); _cacheGardenGathered = true; Thread.Sleep(Usefuls.Latency + 1750); } } } WoWUnit gardenNpc = ObjMgr.GetNearestWoWUnit(ObjMgr.GetWoWUnitByEntry(_npcGarden)); if (gardenNpc.GetBaseAddress != 0) { if (gardenNpc.Position.DistanceTo(me) > 5.0f) { _targetNpc = new Npc { Entry = gardenNpc.Entry, Position = gardenNpc.Position }; MovementManager.FindTarget(ref _targetNpc, 5f); return; } else { Interact.InteractWith(gardenNpc.GetBaseAddress, true); Thread.Sleep(Usefuls.Latency + 1000); Interact.InteractWith(gardenNpc.GetBaseAddress, true); Thread.Sleep(Usefuls.Latency + 500); Lua.LuaDoString("GarrisonCapacitiveDisplayFrame.CreateAllWorkOrdersButton:Click()"); Thread.Sleep(Usefuls.Latency + 1000); } } tList.Pop(); break; case Task.MineWorkOrder: if (display) { Logging.Write("Task: collect mine cache and send work order"); } if (!_cacheMineGathered) { WoWGameObject mineCache = ObjMgr.GetNearestWoWGameObject(ObjMgr.GetWoWGameObjectById(_cacheMine)); if (mineCache.GetBaseAddress != 0) { if (mineCache.Position.DistanceTo(me) > 5.0f) { _targetNpc = new Npc { Entry = mineCache.Entry, Position = mineCache.Position }; MovementManager.FindTarget(ref _targetNpc, 5f); return; } else { Thread.Sleep(Usefuls.Latency + 250); Interact.InteractWith(mineCache.GetBaseAddress, true); _cacheMineGathered = true; Thread.Sleep(Usefuls.Latency + 1750); } } } WoWUnit mineNpc = ObjMgr.GetNearestWoWUnit(ObjMgr.GetWoWUnitByEntry(_npcMine)); if (mineNpc.GetBaseAddress != 0) { if (mineNpc.Position.DistanceTo(me) > 5.0f) { _targetNpc = new Npc { Entry = mineNpc.Entry, Position = mineNpc.Position }; MovementManager.FindTarget(ref _targetNpc, 5f); return; } else { Interact.InteractWith(mineNpc.GetBaseAddress, true); Thread.Sleep(Usefuls.Latency + 1000); Interact.InteractWith(mineNpc.GetBaseAddress, true); Thread.Sleep(Usefuls.Latency + 500); Lua.LuaDoString("GarrisonCapacitiveDisplayFrame.CreateAllWorkOrdersButton:Click()"); Thread.Sleep(Usefuls.Latency + 1000); } } tList.Pop(); break; } if (tList.Count == 0) { Logging.Write("Garrison Farming completed"); CloseProduct(); } }