protected override Composite CreateBehavior() { return(new Zeta.TreeSharp.Action(ret => { bool bExitGame = Exit != null && Exit.ToLower() == "true"; string sThisProfileString = File; // See if there are multiple profile choices, if so split them up and pick a random one if (sThisProfileString.Contains("!")) { string[] sProfileChoices; sProfileChoices = sThisProfileString.Split(new string[] { "!" }, StringSplitOptions.None); Random rndNum = new Random(int.Parse(Guid.NewGuid().ToString().Substring(0, 8), NumberStyles.HexNumber)); int iChooseProfile = rndNum.Next(sProfileChoices.Count()); sThisProfileString = sProfileChoices[iChooseProfile]; } // Now calculate our current path by checking the currently loaded profile string sCurrentProfilePath = Path.GetDirectoryName(Zeta.CommonBot.Settings.GlobalSettings.Instance.LastProfile); // And prepare a full string of the path, and the new .xml file name string sNextProfile = sCurrentProfilePath + @"\" + sThisProfileString; DbHelper.Log(TrinityLogLevel.Normal, LogCategory.UserInformation, "Loading new profile."); ProfileManager.Load(sNextProfile); // A quick nap-time helps prevent some funny issues if (NoDelay == null || NoDelay.ToLower() != "true") { Thread.Sleep(3000); } else { Thread.Sleep(300); } // See if the XML tag requested we exit the game after loading this profile or not if (bExitGame) { DbHelper.Log(TrinityLogLevel.Normal, LogCategory.UserInformation, "Exiting game to continue with next profile."); // Attempt to teleport to town first for a quicker exit int iSafetyLoops = 0; while (!ZetaDia.Me.IsInTown) { iSafetyLoops++; GilesTrinity.WaitWhileAnimating(5, true); ZetaDia.Me.UsePower(SNOPower.UseStoneOfRecall, GilesTrinity.PlayerStatus.CurrentPosition, ZetaDia.Me.WorldDynamicId, -1); Thread.Sleep(1000); GilesTrinity.WaitWhileAnimating(1000, true); if (iSafetyLoops > 5) { break; } } Thread.Sleep(1000); ZetaDia.Service.Party.LeaveGame(); GilesTrinity.ResetEverythingNewGame(); // Wait for 10 second log out timer if not in town, else wait for 3 seconds instead Thread.Sleep(!GilesTrinity.PlayerStatus.IsInTown ? 10000 : 3000); } // Check if we want to restart the game m_IsDone = true; })); }
// Actually deal with a stuck - find an unstuck point etc. public static Vector3 UnstuckHandler(Vector3 vMyCurrentPosition, Vector3 vOriginalDestination) { // Update the last time we generated a path LastGeneratedStuckPosition = DateTime.Now; 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 (iTimesReachedStuckPoint > 0) { vSafeMovementLocation = Vector3.Zero; // Reset the path and allow a whole "New" unstuck generation next cycle iTimesReachedStuckPoint = 0; // And cancel unstucking for 9 seconds so DB can try to navigate iCancelUnstuckerForSeconds = (9 * iTotalAntiStuckAttempts); if (iCancelUnstuckerForSeconds < 20) { iCancelUnstuckerForSeconds = 20; } _lastCancelledUnstucker = DateTime.Now; DbHelper.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) >= 700f) { DbHelper.Log(TrinityLogLevel.Verbose, LogCategory.UserInformation, "You are " + Vector3.Distance(vOriginalDestination, vMyCurrentPosition).ToString() + " distance away from your destination."); DbHelper.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."); iTotalAntiStuckAttempts = 20; } // intell if (iTotalAntiStuckAttempts <= 15) { DbHelper.Log(TrinityLogLevel.Normal, LogCategory.UserInformation, "Your bot got stuck! Trying to unstuck (attempt #{0} of 15 attempts) {1} {2} {3} {4}", iTotalAntiStuckAttempts.ToString(), "Act=\"" + ZetaDia.CurrentAct + "\"", "questId=\"" + ZetaDia.CurrentQuest.QuestSNO + "\"", "stepId=\"" + ZetaDia.CurrentQuest.StepId + "\"", "worldId=\"" + ZetaDia.CurrentWorldId + "\"" ); // check failed minimap markers MiniMapMarker.UpdateFailedMarkers(); DbHelper.Log(TrinityLogLevel.Verbose, LogCategory.UserInformation, "(destination=" + vOriginalDestination.ToString() + ", which is " + Vector3.Distance(vOriginalDestination, vMyCurrentPosition).ToString() + " distance away)"); vSafeMovementLocation = NavHelper.FindSafeZone(true, iTotalAntiStuckAttempts, vMyCurrentPosition); // Temporarily log stuff if (iTotalAntiStuckAttempts == 1 && GilesTrinity.Settings.Advanced.LogStuckLocation) { FileStream LogStream = File.Open(Path.Combine(FileManager.LoggingPath, "Stucks - " + GilesTrinity.PlayerStatus.ActorClass.ToString() + ".log"), FileMode.Append, FileAccess.Write, FileShare.Read); using (StreamWriter LogWriter = new StreamWriter(LogStream)) { LogWriter.WriteLine(DateTime.Now.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 iTotalAntiStuckAttempts++; return(vSafeMovementLocation); } iTimesReachedMaxUnstucks++; iTotalAntiStuckAttempts = 1; vSafeMovementLocation = Vector3.Zero; vOldPosition = Vector3.Zero; iTimesReachedStuckPoint = 0; TimeLastRecordedPosition = DateTime.MinValue; LastGeneratedStuckPosition = DateTime.MinValue; // int iSafetyLoops = 0; if (iTimesReachedMaxUnstucks == 1) { Navigator.Clear(); DbHelper.Log(TrinityLogLevel.Normal, LogCategory.Movement, "Anti-stuck measures now attempting to kickstart DB's path-finder into action."); Navigator.MoveTo(vOriginalDestination, "original destination", false); iCancelUnstuckerForSeconds = 40; _lastCancelledUnstucker = DateTime.Now; return(vSafeMovementLocation); } if (iTimesReachedMaxUnstucks == 2) { DbHelper.Log(TrinityLogLevel.Normal, LogCategory.Movement, "Anti-stuck measures failed. Now attempting to reload current profile."); Navigator.Clear(); ProfileManager.Load(Zeta.CommonBot.ProfileManager.CurrentProfile.Path); DbHelper.Log(TrinityLogLevel.Normal, 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 (GilesTrinity.Settings.Advanced.AllowRestartGame && DateTime.Now.Subtract(timeLastRestartedGame).TotalMinutes >= 15) { timeLastRestartedGame = DateTime.Now; string sUseProfile = GilesTrinity.FirstProfile; DbHelper.Log(TrinityLogLevel.Normal, LogCategory.UserInformation, "Anti-stuck measures exiting current game."); // Load the first profile seen last run ProfileManager.Load(!string.IsNullOrEmpty(sUseProfile) ? sUseProfile : Zeta.CommonBot.ProfileManager.CurrentProfile.Path); Thread.Sleep(1000); GilesTrinity.ResetEverythingNewGame(); ZetaDia.Service.Party.LeaveGame(); // Wait for 10 second log out timer if not in town if (!ZetaDia.Me.IsInTown) { Thread.Sleep(15000); } } else { DbHelper.Log(TrinityLogLevel.Normal, LogCategory.UserInformation, "Unstucking measures failed. Now stopping Trinity unstucker for 12 minutes to inactivity timers to kick in or DB to auto-fix."); iCancelUnstuckerForSeconds = 720; _lastCancelledUnstucker = DateTime.Now; return(vSafeMovementLocation); } return(vSafeMovementLocation); }