/// <summary> /// Processes the routine of engaging & fighting an enemy. /// </summary> /// <param name="target">The ID of the target to engage.</param> /// <param name="monster">The monster object for the monster you're engaging</param> /// <param name="mode">Special mode considerations for engaging this target.</param> /// <param name="fail"></param> /// <returns></returns> public static bool Fight(int target, Monster monster, Mode mode, out FailType fail) { fail = FailType.NoFail; _fighting = true; float targetX = 0; float targetZ = 0; job.SetBattle(true); fface.Navigator.Reset(); if (mode == Mode.Meshing) { List <Node> path = new List <Node>(); float destinationX = fface.NPC.PosX(target); float destinationZ = fface.NPC.PosZ(target); path = GetPath(destinationX, destinationZ); if (!path.Any()) { fail = FailType.NoPath; _fighting = false; } while (path.Any() && job.CanStillAttack(target) && DistanceTo(target) > (monster.HitBox * 1.5) && _fighting) { if (!fface.NPC.IsClaimed(target) && _fighting) { Target(target); job.UseClaim(); } if (_fighting) { targetX = path[0].X; targetZ = path[0].Z; if (!IsPositionSafe(Convert.ToInt32(targetX), Convert.ToInt32(targetZ))) { _fighting = false; } fface.Navigator.HeadingTolerance = 2; fface.Navigator.DistanceTolerance = 0.7; path.RemoveAt(0); fface.Navigator.Goto(() => targetX, () => targetZ, false); } Thread.Sleep(1); } fface.Navigator.Reset(); } // battle routine while (job.CanStillAttack(target) && _fighting) { while (fface.Player.Status == Status.Fighting && fface.Target.ID != target) { fface.Windower.SendString("/attackoff"); Thread.Sleep(3000); fface.Windower.SendKeyPress(KeyCode.EscapeKey); Thread.Sleep(1000); } // TARGET Target(target); // FACE TARGET fface.Navigator.FaceHeading(target); // CLAIM if (!fface.NPC.IsClaimed(target) && _fighting) { switch (mode) { case Mode.StrictPathing: { // We don't want to wonder too far from our strict path. Use Strict Pathing. if (DistanceTo(target) >= monster.HitBox * 1.5) { fface.Navigator.Reset(); } Thread.Sleep(500); job.UseRangedClaim(); break; } case Mode.Meshing: case Mode.None: { job.UseClaim(); break; } } } // ENGAGE if (fface.Player.Status != Status.Fighting && job.CanStillAttack(target) && _fighting) { job.Engage(); } // make sure we're in the correct position if (!job.Position(target, monster, mode)) { _fighting = false; } if (job.GetHaltActions()) { Thread.Sleep(2); continue; } // PLAYER STUFF if (fface.Player.Status == Status.Fighting && _fighting && fface.Player.MainJob != Job.GEO && fface.Player.MainJob != Job.WHM && fface.Player.MainJob != Job.BRD && fface.Player.MainJob != Job.BLM) { job.UseHeals(); job.UseAbilities(); if (fface.Player.TPCurrent >= 1000) { job.UseWeaponskills(); } job.UseSpells(); } else if ((fface.Player.MainJob == Job.WHM || fface.Player.MainJob == Job.BLM || fface.Player.MainJob == Job.GEO || fface.Player.MainJob == Job.BRD) && _fighting) { fface.Navigator.Reset(); if (fface.Player.MainJob == Job.BLM) { job.UseAbilities(); } job.UseSpells(); } Thread.Sleep(2); } Thread.Sleep(500); if (!_fighting && fface.Player.Status == Status.Fighting) { WriteLog("[NAV] Monster is out of mesh. Giving up..."); fface.Windower.SendString("/attackoff"); Thread.Sleep(3000); if (fface.Target.IsLocked) { fface.Windower.SendString("/lockon"); Thread.Sleep(500); } } fface.Windower.SendKey(KeyCode.NP_Number2, false); fface.Windower.SendKey(KeyCode.NP_Number4, false); fface.Windower.SendKey(KeyCode.NP_Number6, false); job.SetBattle(false); _fighting = false; if (!_fighting || fface.NPC.HPPCurrent(target) != 0) { return(false); } Black.Clear(); return(true); }