Advertisement
Guest User

Untitled

a guest
Aug 3rd, 2015
119
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 14.10 KB | None | 0 0
  1. using System.Collections.Generic;
  2. using System.Diagnostics;
  3. using System.Linq;
  4. using System.Threading.Tasks;
  5. using System.Windows.Controls;
  6. using log4net;
  7. using Loki.Bot;
  8. using Loki.Common;
  9. using Loki.Game;
  10. using Loki.Game.GameData;
  11. using Loki.Game.Objects;
  12. using Loki.Game.Objects.Items;
  13.  
  14. namespace ExtendedPlayerMover
  15. {
  16. internal class ExtendedPlayerMover : IPlugin
  17. {
  18. private static readonly ILog Log = Logger.GetLoggerInstanceForType();
  19.  
  20. private bool _enabled;
  21. private SkillPlayerMover _mover = new SkillPlayerMover();
  22.  
  23. /// <summary> The name of the plugin. </summary>
  24. public string Name
  25. {
  26. get { return "ExtendedPlayerMover"; }
  27. }
  28.  
  29. /// <summary> The description of the plugin. </summary>
  30. public string Description
  31. {
  32. get { return "A modified version of CustomPlayerMover compatible with all four movement skills and quicksilver flasks."; }
  33. }
  34.  
  35. /// <summary>The author of the plugin.</summary>
  36. public string Author
  37. {
  38. get { return "Bossland GmbH & Infinite Monkeys"; }
  39. }
  40.  
  41. /// <summary>The version of the plugin.</summary>
  42. public string Version
  43. {
  44. get
  45. {
  46. return "1.0";
  47. }
  48. }
  49.  
  50. /// <summary>Initializes this plugin.</summary>
  51. public void Initialize()
  52. {
  53. Log.DebugFormat("[ExtendedPlayerMover] Initialize");
  54. }
  55.  
  56. public void Deinitialize()
  57. {
  58. Log.DebugFormat("[ExtendedPlayerMover] Deinitialize");
  59. }
  60.  
  61. /// <summary> The plugin start callback. Do any initialization here. </summary>
  62. public void Start()
  63. {
  64. Log.DebugFormat("[ExtendedPlayerMover] Start");
  65.  
  66. // This is all that needs to be done. All movement logic that uses PlayerMover.MoveTowards
  67. // will now use this new instance's implementation.
  68. PlayerMover.Instance = _mover;
  69. _mover.SkillSlot = -1; // reset the skill slot in case the user changed something
  70.  
  71. Log.InfoFormat("[ExtendedPlayerMover] Now setting the SkillPlayerMover.");
  72. }
  73.  
  74. /// <summary> The plugin tick callback. Do any update logic here. </summary>
  75. public void Tick()
  76. {
  77. }
  78.  
  79. /// <summary> The plugin stop callback. Do any pre-dispose cleanup here. </summary>
  80. public void Stop()
  81. {
  82. Log.DebugFormat("[ExtendedPlayerMover] Stop");
  83. }
  84.  
  85. #region Implementation of IConfigurable
  86.  
  87. public JsonSettings Settings
  88. {
  89. get { return null; }
  90. }
  91.  
  92. /// <summary> The plugin's settings control. This will be added to the Exilebuddy Settings tab.</summary>
  93. public UserControl Control
  94. {
  95. get { return null; }
  96. }
  97.  
  98. #endregion
  99.  
  100.  
  101. #region Implementation of ILogic
  102.  
  103. /// <summary>
  104. /// Coroutine logic to execute.
  105. /// </summary>
  106. /// <param name="type">The requested type of logic to execute.</param>
  107. /// <param name="param">Data sent to the object from the caller.</param>
  108. /// <returns>true if logic was executed to handle this type and false otherwise.</returns>
  109. public async Task<bool> Logic(string type, params dynamic[] param)
  110. {
  111. return false;
  112. }
  113.  
  114. /// <summary>
  115. /// Non-coroutine logic to execute.
  116. /// </summary>
  117. /// <param name="name">The name of the logic to invoke.</param>
  118. /// <param name="param">The data passed to the logic.</param>
  119. /// <returns>Data from the executed logic.</returns>
  120. public object Execute(string name, params dynamic[] param)
  121. {
  122. return null;
  123. }
  124.  
  125. #endregion
  126.  
  127. #region Implementation of IEnableable
  128.  
  129. /// <summary> The plugin is being enabled.</summary>
  130. public void Enable()
  131. {
  132. Log.DebugFormat("[ExtenderPlayerMover] Enable");
  133. }
  134.  
  135. /// <summary> The plugin is being disabled.</summary>
  136. public void Disable()
  137. {
  138. Log.DebugFormat("[ExtenderPlayerMover] Disable");
  139. }
  140.  
  141. #endregion
  142.  
  143. #region Override of Object
  144.  
  145. /// <summary>Returns a string that represents the current object.</summary>
  146. /// <returns>A string that represents the current object.</returns>
  147. public override string ToString()
  148. {
  149. return Name + ": " + Description;
  150. }
  151.  
  152. #endregion
  153. }
  154.  
  155. /// <summary>
  156. /// A player mover that uses movement skills and adrenaline potions to try and move around.
  157. /// This mover pathfinds each operation to the destination to try and avoid desync issues.
  158. /// </summary>
  159. public class SkillPlayerMover : IPlayerMover
  160. {
  161. private static readonly ILog Log = Logger.GetLoggerInstanceForType();
  162.  
  163. private readonly Stopwatch _speedFlaskCd = new Stopwatch();
  164.  
  165. internal int SkillSlot = -1;
  166. internal bool useQuicksilver = false;
  167.  
  168. //Position of each skill, so that if there's more than one available
  169. //we can find the one with the highest slot value and use that.
  170. private int Skill1Slot = -1;
  171. private int Skill2Slot = -1;
  172. private int Skill3Slot = -1;
  173. private int Skill4Slot = -1;
  174.  
  175. private string _activeMoveSkill;
  176. private readonly Stopwatch _skillStopwatch = new Stopwatch();
  177.  
  178. //Stolen from ExtenderPlayerMover
  179. private bool FlaskHelper(Stopwatch sw, int flaskCdMs, IEnumerable<Item> flasks)
  180. {
  181. var useFlask = false;
  182. if (!sw.IsRunning)
  183. {
  184. sw.Start();
  185. useFlask = true;
  186. }
  187. else if (sw.ElapsedMilliseconds > Loki.Bot.Logic.Bots.OldGrindBot.Utility.LatencySafeValue(flaskCdMs))
  188. {
  189. sw.Restart();
  190. useFlask = true;
  191. }
  192.  
  193. if (useFlask)
  194. {
  195. var flask = flasks.FirstOrDefault();
  196. if (flask != null)
  197. {
  198. var err = LokiPoe.InGameState.QuickFlaskPanel.UseFlask(flask);
  199. if (err != LokiPoe.InGameState.UseFlaskError.None)
  200. {
  201. Log.ErrorFormat("[FlaskHelper] QuickFlaskPanel.UseFlask returned {0}.", err);
  202. }
  203. return true;
  204. }
  205. }
  206.  
  207. return false;
  208. }
  209.  
  210. //Quicksilver Flasks
  211. public static IEnumerable<Item> SpeedFlasks
  212. {
  213. get
  214. {
  215. var inv = LokiPoe.InGameState.QuickFlaskPanel.Flasks;
  216. return from item in inv
  217. let flask = item as Flask
  218. where flask != null && flask.Name.Contains("Quicksilver Flask") && flask.CanUse
  219. select item;
  220. }
  221. }
  222.  
  223. /// <summary>
  224. /// Attempts to move towards a position. This function will perform pathfinding logic and take into consideration move distance
  225. /// to try and smoothly move towards a point.
  226. /// </summary>
  227. /// <param name="position">The position to move towards.</param>
  228. /// <param name="user">A user object passed.</param>
  229. /// <returns>true if the position was moved towards, and false if there was a pathfinding error.</returns>
  230. public bool MoveTowards(Vector2i position, params dynamic[] user)
  231. {
  232. var me = LokiPoe.Me;
  233. var myPos = me.Position;
  234.  
  235. var path = new Loki.Bot.Pathfinding.PathfindingCommand(myPos, position, 10);
  236. if (Loki.Bot.Pathfinding.ExilePather.FindPath(ref path))
  237. {
  238. if (path.Error == Loki.Bot.Pathfinding.PathfindingError.StartNotNavigable ||
  239. path.Error == Loki.Bot.Pathfinding.PathfindingError.StartAndEndAreSame)
  240. {
  241. var rnd = LokiPoe.Me.Position;
  242. rnd += new Vector2i(Loki.Game.LokiPoe.Random.Next(-25, 26), Loki.Game.LokiPoe.Random.Next(-25, 26));
  243.  
  244. Log.DebugFormat("[MoveTowards] FindPath returned {0}. Now clicking the random position {1}.",
  245. path.Error, rnd);
  246.  
  247. LokiPoe.Input.SetMousePos(rnd);
  248.  
  249. LokiPoe.Input.Move();
  250.  
  251. return true;
  252. }
  253.  
  254. Log.ErrorFormat("[MoveTowards] FindPath returned {0}.", path.Error);
  255.  
  256. return false;
  257. }
  258.  
  259. var distance = myPos.Distance(position); ; //As the crow flies, for now at least.
  260. if (distance > 200)
  261. {
  262. FlaskHelper(_speedFlaskCd, 5000, SpeedFlasks); //I'll un-hardcode this at some point, maybe
  263. }
  264.  
  265. var point = Vector2i.Zero;
  266.  
  267. var checkSkill = true;
  268. var canSkill = false;
  269. var skillPos = Vector2i.Zero;
  270.  
  271. // Only check for using skill once every 300ms.
  272. if (_skillStopwatch.IsRunning && _skillStopwatch.ElapsedMilliseconds < 300)
  273. {
  274. checkSkill = false;
  275. }
  276.  
  277. // Don't try to custom move in these areas.
  278. if (LokiPoe.Me.IsInTown || LokiPoe.Me.IsInMapRoom || LokiPoe.Me.IsInHideout)
  279. checkSkill = false;
  280.  
  281. if (SkillSlot == -1 && useQuicksilver == false)
  282. {
  283. //This isn't very neat but it works so whatever
  284. var LW = LokiPoe.Me.AvailableSkills.FirstOrDefault(s => s.Name == "Lightning Warp" && s.IsOnSkillBar);
  285. var LS = LokiPoe.Me.AvailableSkills.FirstOrDefault(s => s.Name == "Leap Slam" && s.IsOnSkillBar);
  286. var WB = LokiPoe.Me.AvailableSkills.FirstOrDefault(s => s.Name == "Whirling Blades" && s.IsOnSkillBar);
  287. var BA = LokiPoe.Me.AvailableSkills.FirstOrDefault(s => s.Name == "Blink Arrow" && s.IsOnSkillBar);
  288.  
  289. List<int> skills = new List<int>();
  290.  
  291. if (LW != null)
  292. {
  293. skills.Add(LW.Slot);
  294. Log.DebugFormat("[ExtendedPlayerMover] Found Lightning Warp in slot {0}", LW.Slot);
  295. }
  296. if (LS != null)
  297. {
  298. skills.Add(LS.Slot);
  299. Log.DebugFormat("[ExtendedPlayerMover] Found Leap Slam in slot {0}", LS.Slot);
  300. }
  301. if (WB != null)
  302. {
  303. skills.Add(WB.Slot);
  304. Log.DebugFormat("[ExtendedPlayerMover] Found Whirling Blades in slot {0}", WB.Slot);
  305. }
  306. if (BA != null)
  307. {
  308. skills.Add(BA.Slot);
  309. Log.DebugFormat("[ExtendedPlayerMover] Found Blink Arrow in slot {0}", BA.Slot);
  310. }
  311.  
  312. if (skills.Count != 0)
  313. SkillSlot = skills.Max();
  314.  
  315. // No movement skill, see if they have any quicksilver flasks.
  316. if (SkillSlot == -1)
  317. {
  318. checkSkill = false;
  319. Log.DebugFormat("[ExtendedPlayerMover] No movement skill found, checking for quicksilver flasks");
  320.  
  321. if (SpeedFlasks != null)
  322. {
  323. useQuicksilver = true;
  324. Log.DebugFormat("[ExtendedPlayerMover] Found quicksilver flask(s), using them");
  325. }
  326. }
  327. }
  328.  
  329. if (LokiPoe.CurrentWorldArea.IsTown)
  330. {
  331. // To avoid some issues in Act 2 stairs, we try to take points closer to us rather than the other way around.
  332. point = path.Path.FirstOrDefault(e => e.Distance(myPos) > 8);
  333. }
  334. else
  335. {
  336. // TODO: Tweak/change this logic as needed per tileset.
  337. // Smaller closed areas should probably just skip trying to use movement skills.
  338.  
  339. for (var i = path.Path.Count - 1; i > 0; --i)
  340. {
  341. point = path.Path[i];
  342.  
  343. if (checkSkill && !canSkill && point.Distance(myPos) <= 60)
  344. {
  345. if (Loki.Bot.Pathfinding.ExilePather.CanObjectSee(LokiPoe.Me, point) && !Loki.Bot.Logic.Bots.OldGrindBot.Utility.ClosedDoorBetween(myPos, point))
  346. {
  347. canSkill = true;
  348. skillPos = point;
  349. }
  350. }
  351.  
  352. if (point.Distance(myPos) <= 20)
  353. break;
  354. }
  355. }
  356.  
  357. if (point == Vector2i.Zero)
  358. {
  359. point = path.Path.Last();
  360. }
  361.  
  362. // Find a point in the direction we want to move, but keep it random to make sure bots do not do the same thing everytime.
  363.  
  364.  
  365. var abc = myPos.GetPointAtDistanceAfterThis(point, Loki.Game.LokiPoe.Random.Next(14, 20));
  366. point += new Vector2i(Loki.Game.LokiPoe.Random.Next(-2, 3), Loki.Game.LokiPoe.Random.Next(-2, 3));
  367.  
  368. // Try to use movement skill
  369. if (canSkill)
  370. {
  371. var res = LokiPoe.InGameState.SkillBarPanel.UseAt(SkillSlot, false, skillPos);
  372. if (res == LokiPoe.InGameState.UseError.None)
  373. {
  374. if (LokiPoe.Me.HasCurrentAction)
  375. {
  376. if (LokiPoe.Me.CurrentAction.Skill.Name == _activeMoveSkill)
  377. {
  378. _skillStopwatch.Restart();
  379. return true;
  380. }
  381. }
  382. }
  383. }
  384.  
  385. // Otherwise, normal movement to keep on going.
  386. LokiPoe.Input.SetMousePos(point);
  387. LokiPoe.Input.Move();
  388.  
  389. return true;
  390. }
  391. }
  392. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement