public WoWPoint GetSidePoint(float degrees, float distance = 5f) { float facing = WoWMathHelper.DegreesToRadians(degrees); facing = WoWMathHelper.NormalizeRadian(facing); return(Location.RayCast(facing, distance)); }
private bool IsWithinArticulationLimits(WoWUnit vehicle, WoWUnit potentialTarget) { if ((vehicle == null) || !vehicle.IsValid) { return(false); } if ((potentialTarget == null) || !potentialTarget.IsValid) { return(false); } double neededAzimuth = Math.Atan((potentialTarget.Location.Z - vehicle.Location.Z) / vehicle.Location.Distance2D(potentialTarget.Location)); double neededFacing = WoWMathHelper.CalculateNeededFacing(vehicle.Location, potentialTarget.Location); neededFacing = WoWMathHelper.NormalizeRadian((float)neededFacing); if ((neededFacing < CannonArticulation_HeadingMin) || (neededFacing > CannonArticulation_HeadingMax)) { return(false); } if ((neededAzimuth < CannonArticulation_AzimuthMin) || (neededAzimuth > CannonArticulation_AzimuthMax)) { return(false); } return(true); }
public WoWPoint GetFrontPoint(float distance = 5f) { float facing = RefWoWObject.Rotation; facing = WoWMathHelper.NormalizeRadian(facing); return(Location.RayCast(facing, distance)); }
// The HB API always returns 0 for our facing when we're in a vehicle. // To get the actualy value, we must ask the WoWclient directly. private float GetVehicleFacing() { return (Query.IsInVehicle() ? WoWMathHelper.NormalizeRadian(Lua.GetReturnVal <float>("return GetPlayerFacing();", 0)) : Me.RenderFacing); }
public WoWPoint GetBehindPoint(float distance = 5f) { float facing = RefWoWObject.Rotation; facing += WoWMathHelper.DegreesToRadians(180); facing = WoWMathHelper.NormalizeRadian(facing); return(Location.RayCast(facing, distance)); }
public static WoWPoint CalculatePointBehindTarget() { float facing = StyxWoW.Me.CurrentTarget.Rotation; facing += WoWMathHelper.DegreesToRadians(180); // was 150 ? facing = WoWMathHelper.NormalizeRadian(facing); return(StyxWoW.Me.CurrentTarget.Location.RayCast(facing, Spell.MeleeRange - 2f)); }
private async Task <bool> UtilityCoroutine_MoveAndUseCatapult() { if (!Query.IsInVehicle() || !IsViable(SelectedCatapult)) { return(false); } // Move vehicle into position... if (!Navigator.AtLocation(CurrentTask.PositionForLaunch)) { Navigator.MoveTo(CurrentTask.PositionForLaunch); return(true); } // Adjust heading... if (!WoWMathHelper.IsFacing(WoWMovement.ActiveMover.Location, GetVehicleFacing(), CurrentTask.PositionToLand, WoWMathHelper.DegreesToRadians(0.5f))) { // Handle heading... double neededHeading = WoWMathHelper.CalculateNeededFacing(Me.Location, CurrentTask.PositionToLand); neededHeading = WoWMathHelper.NormalizeRadian((float)neededHeading); QBCLog.Info("Adjusting firing heading"); Me.SetFacing((float)neededHeading); await Coroutine.Sleep(200); return(true); } // Adjust azimuth... double currentAzimuth = WoWMathHelper.NormalizeRadian(Lua.GetReturnVal <float>("return VehicleAimGetAngle();", 0)); double neededAzimuth = NormalizeAngleToPi(CurrentTask.NeededAzimuth); double azimuthChangeRequired = neededAzimuth - currentAzimuth; if (Math.Abs(azimuthChangeRequired) >= 0.01) { QBCLog.Info("Adjusting firing azimuth"); // NB: VehicleAimIncrement() handles negative values of 'increment' correctly... Lua.DoString("VehicleAimIncrement({0})", azimuthChangeRequired); await Coroutine.Sleep(200); return(true); } // Fire.. QBCLog.Info("Firing Catapult"); Lua.DoString(Lua_LaunchCommand); await Coroutine.Wait(3000, () => !Query.IsInVehicle()); return(true); }
public static bool IsFacing2D(WoWPoint me, float myFacingRadians, WoWPoint target, float arcRadians) { me.Z = target.Z = 0; arcRadians = WoWMathHelper.NormalizeRadian(arcRadians); float num = WoWMathHelper.CalculateNeededFacing(me, target); float num2 = WoWMathHelper.NormalizeRadian(num - myFacingRadians); if (num2 > 3.1415926535897931) { num2 = (float)(6.2831853071795862 - num2); } bool result = (num2 <= arcRadians / 2f); return(result); }
//if pool is between CurrentPoint and NextPoint then cycle to nextPoint public void CycleToNextIfBehind(WoWGameObject pool) { WoWPoint cp = CurrentPoint; WoWPoint point = GetNextWayPoint(); point = new WoWPoint(point.X - cp.X, point.Y - cp.Y, 0); point.Normalize(); float angle = WoWMathHelper.NormalizeRadian((float)Math.Atan2(point.Y, point.X - 1)); if (WoWMathHelper.IsFacing(CurrentPoint, angle, pool.Location) && CurrentPoint != WayPoints[WayPoints.Count - 1]) { CycleToNextPoint(); } }
internal EncounterInfo Update() { var hostileForces = (from unit in ObjectManager.GetObjectsOfTypeFast <WoWUnit>() where unit.FactionId == 2334 && unit.IsAlive let loc = unit.Location orderby loc.DistanceSqr(_encounterLocaction) // project WoWUnit.Location to minimize the number of injections. select new { Location = loc, Unit = unit }).ToList(); var friendlyForces = (from unit in ObjectManager.GetObjectsOfTypeFast <WoWUnit>() where unit.FactionId == 2333 && unit.IsAlive let loc = unit.Location orderby loc.DistanceSqr(_encounterLocaction) select new { Location = loc, Unit = unit }).ToList(); var bestVolleyTarget = hostileForces.OrderByDescending( u => hostileForces.Count(v => v != u && v.Location.DistanceSqr(u.Location) < 10 * 10)).FirstOrDefault(); VolleyPosition = bestVolleyTarget != null ? bestVolleyTarget.Location.RayCast( WoWMathHelper.NormalizeRadian(bestVolleyTarget.Unit.Rotation), bestVolleyTarget.Location.Distance(_encounterLocaction) * bestVolleyTarget.Unit.MovementInfo.CurrentSpeed * 0.04f) : WoWPoint.Empty; var nearbyHostileUnit = hostileForces.FirstOrDefault(u => u.Location.DistanceSqr(_encounterLocaction) <= 30 * 30); ChampionRallyPosition = nearbyHostileUnit != null && !friendlyForces.Any( u => u.Unit.Entry == RamkahenChampionId && u.Location.DistanceSqr(nearbyHostileUnit.Location) < 12 * 12) ? nearbyHostileUnit.Location : WoWPoint.Empty; var radianceTargetUnit = friendlyForces.Where(u => u.Unit.HealthPercent < 70).OrderByDescending(u => friendlyForces.Count(v => v.Unit.HealthPercent < 70)) .FirstOrDefault() ?? nearbyHostileUnit; RadianceTarget = radianceTargetUnit != null ? radianceTargetUnit.Location : WoWPoint.Empty; return(this); }
private Vector3 FindNewStationPoint(WoWUnit desiredTarget, double offsetRadians = 0.0) { if (!Query.IsViable(desiredTarget)) { desiredTarget = FindMobToKill(MobId_ScarletBallista); } var myLocation = WoWMovement.ActiveMover.Location; var preferredDistance = StyxWoW.Random.Next((int)TargetDistance2DMin + 1, (int)TargetDistance2DMax); var targetLocation = desiredTarget.Location; // To evade, we just rotate in a (counter-clockwise) circle around our selected target... var escapeHeading = WoWMathHelper.CalculateNeededFacing(targetLocation, myLocation); escapeHeading = WoWMathHelper.NormalizeRadian((float)(escapeHeading + offsetRadians + (TAU / 14))); var escapePoint = targetLocation.RayCast(escapeHeading, (float)preferredDistance); return(new Vector3(escapePoint.X, escapePoint.Y, targetLocation.Z).Add(0.0, 0.0, TargetHeightMinimum + TargetHeightVariance)); }
// NB: In WoW, larger headings are to left, and larger Azimuths are up private void AimAndFireCannon(WoWUnit vehicle, WoWUnit target) { // Handle heading... double traveltime = target.Distance / (NurongsCannonShot_FeetPerSecond * 3.0f /*feet to yards*/); WoWPoint targetLeadPoint = target.Location.RayCast(target.RenderFacing, (float)(target.MovementInfo.CurrentSpeed * traveltime)); float neededHeading = WoWMathHelper.CalculateNeededFacing(Me.Location, targetLeadPoint); neededHeading = WoWMathHelper.NormalizeRadian(neededHeading); Me.SetFacing(neededHeading); // Handle Azimuth... // "Location" is measured at the feet of the toon. We want to aim for the 'middle' of the toon's // height. double currentAzimuth = NormalizeAngleToPi(Lua.GetReturnVal <double>("return VehicleAimGetAngle();", 0)); double neededAzimuth = Math.Atan((target.Location.Z - vehicle.Location.Z + (GetBoundingHeight(target) / 2)) // Middle of toon height / vehicle.Location.Distance2D(target.Location)); neededAzimuth = NormalizeAngleToPi(neededAzimuth); // Execute fire... // NB: VehicleAimIncrement() handles negative values of 'increment' correctly... Lua.DoString("VehicleAimIncrement({0}); {1}", (neededAzimuth - currentAzimuth), NurongsCannonShot_LuaCommand); }
private Composite CreateCombatBehavior() { // NB: We'll be running right over some hostiles while in the barrel. // Even with a PullDistance set to one, HBcore and the CombatRoutine are going to try to pull these mobs. // Thus, this behavior runs at "higher than combat" priority, and prevents the CombatRoutine from executing // while this behavior is in progress. // // NB: We need to allow lower BT nodes to run when the behavior is finished; otherwise, HB will not // process the change of _isBehaviorDone state. return(new Decorator(context => !_isBehaviorDone, new PrioritySelector(context => _combatContext.Update(), // If quest is done, behavior is done... new Decorator(context => !UtilIsProgressRequirementsMet(QuestId, QuestRequirementInLog, QuestRequirementComplete), new Action(context => { _isBehaviorDone = true; QBCLog.Info("Finished"); })), // If not in Keg Bomb Vehicle, move to it and get inside... new Decorator(context => !Query.IsInVehicle() && (_combatContext.KegBomb != null), new PrioritySelector( new Decorator(context => _combatContext.KegBomb.Distance > _combatContext.KegBomb.InteractRange, new Action(context => { Navigator.MoveTo(_combatContext.KegBomb.Location); })), new Decorator(context => Me.IsMoving, new Action(context => { WoWMovement.MoveStop(); })), new Decorator(context => !Me.IsSafelyFacing(_combatContext.KegBomb), new Action(context => { _combatContext.KegBomb.Face(); })), new Sequence( // N.B. we need to wait a bit before jumping in vehicle after a round - // due to a bug that prevents bot from leaving vehicle until a relog new WaitContinue(2, context => false, new ActionAlwaysSucceed()), new Action(context => { _combatContext.ReInitialize(); _combatContext.KegBomb.Interact(); QBCLog.Info("Started barrel roll #{0}", ++_barrelRollCount); return RunStatus.Failure; })), new Wait(TimeSpan.FromMilliseconds(1000), context => false, new ActionAlwaysSucceed()) )), // If we are in the vehicle... new Decorator(context => Query.IsInVehicle() && (_combatContext.KegBombVehicle != null), new PrioritySelector( // If we've been in the barrel too long, just blow it up... // Blacklist whatever target we were after, and try again new Decorator(context => (_combatContext.BarrelRollingTimer.ElapsedMilliseconds > BarrelRollingTimeBeforeRetrying) && !_combatContext.IsKegIgnited, new Action(context => { QBCLog.Warning("We've been in the barrel too long--we're blowing it up to try again"); IgniteKeg(_combatContext); if (_combatContext.SelectedTarget != null) { Blacklist.Add(_combatContext.SelectedTarget, BlacklistFlags.Combat, TimeSpan.FromMinutes(3)); } })), // Select target, if not present... new Decorator(context => _combatContext.SelectedTarget == null, new Action(context => ChooseTarget(_combatContext))), // If we have a target, guide barrel to target... new Decorator(context => _combatContext.SelectedTarget != null, new Action(context => { float neededFacing = WoWMathHelper.CalculateNeededFacing(_combatContext.KegBombVehicle.Location, _combatContext.SelectedTarget.Location); neededFacing = WoWMathHelper.NormalizeRadian(neededFacing); float neededRotation = Math.Abs(neededFacing - _combatContext.KegBombVehicle.RenderFacing); neededRotation = WoWMathHelper.NormalizeRadian(neededRotation); // If we need to rotate heading 'too hard' to hit the target, then we missed the target... // Blow up the current barrel, blacklist the target, and try again if (((neededRotation > (Math.PI / 2)) && (neededRotation < ((Math.PI * 2) - (Math.PI / 2)))) && !_combatContext.IsKegIgnited) { QBCLog.Warning("We passed the selected target--igniting barrel to try again."); IgniteKeg(_combatContext); Blacklist.Add(_combatContext.SelectedTarget, BlacklistFlags.Combat, TimeSpan.FromMinutes(3)); } // Ignite the keg at the appropriate time... if (_combatContext.SelectedTarget.Distance <= IgniteDistance) { IgniteKeg(_combatContext); } // Guide the keg to target... Me.SetFacing(neededFacing); return RunStatus.Success; })) )) ))); }
public Vector3 FindLocation(Vector3 ptOrigin) { DateTime startFind = DateTime.UtcNow; int countPointsChecked = 0; int countFailDiff = 0; int countFailTrace = 0; int countFailToPointNav = 0; int countFailRange = 0; int countFailSafe = 0; int countFailToPointLoS = 0; int countFailToMobLoS = 0; TimeSpan spanTrace = TimeSpan.Zero; TimeSpan spanNav = TimeSpan.Zero; double furthestNearMobDistSqr = 0f; Vector3 ptFurthest = Vector3.Zero; float facingFurthest = 0f; bool reallyCheckRangeToLineOfSightMob = CheckRangeToLineOfSightMob && Me.GotTarget; Vector3 ptAdjOrigin = ptOrigin; // ptAdjOrigin.Z += 1f; // comment out origin adjustment since using GetTraceLinePos() Vector3 ptDestination = new Vector3(); List <Vector3> mobLocations = new List <Vector3>(); float arcIncrement = ((float)Math.PI * 2) / RaysToCheck; mobLocations = AllEnemyMobLocationsToCheck; double minSafeDistSqr = MinSafeDistance * MinSafeDistance; float baseDestinationFacing; if (PreferredDirection == Direction.None && MobToRunFrom != null) { baseDestinationFacing = Styx.Helpers.WoWMathHelper.CalculateNeededFacing(MobToRunFrom.Location, Me.Location); } else if (PreferredDirection == Direction.Frontwards) { baseDestinationFacing = Me.RenderFacing; } else // if (PreferredDirection == Disengage.Direction.Backwards) { baseDestinationFacing = Me.RenderFacing + (float)Math.PI; } L.debugLog("SafeArea: facing {0:F0} degrees, looking for safespot towards {1:F0} degrees", C.DefensiveColor, WoWMathHelper.RadiansToDegrees(Me.RenderFacing), WoWMathHelper.RadiansToDegrees(baseDestinationFacing) ); for (int arcIndex = 0; arcIndex < RaysToCheck; arcIndex++) { // rather than tracing around the circle, toggle between clockwise and counter clockwise for each test // .. so we favor a position furthest away from mob float checkFacing = baseDestinationFacing; if ((arcIndex & 1) == 0) { checkFacing += arcIncrement * (arcIndex >> 1); } else { checkFacing -= arcIncrement * ((arcIndex >> 1) + 1); } checkFacing = WoWMathHelper.NormalizeRadian(checkFacing); for (float distFromOrigin = MinScanDistance; distFromOrigin <= MaxScanDistance; distFromOrigin += IncrementScanDistance) { countPointsChecked++; ptDestination = ptOrigin.RayCast(checkFacing, distFromOrigin); L.debugLog("SafeArea: checking {0:F1} degrees at {1:F1} yds", WoWMathHelper.RadiansToDegrees(checkFacing), distFromOrigin); DateTime start = DateTime.UtcNow; bool failTrace = MeshTraceline(Me.Location, ptDestination); spanTrace += DateTime.UtcNow - start; bool failNav; if (DirectPathOnly) { failNav = failTrace; spanNav = spanTrace; } else { start = DateTime.UtcNow; failNav = false; //failNav = !Navigator.CanNavigateFully(Me.Location, ptDestination); spanNav += DateTime.UtcNow - start; } if (failTrace) { countFailTrace++; } if (failTrace != failNav) { countFailDiff++; } if (failNav) { // L.debugLog( Color.Cyan, "Safe Location failed navigation check for degrees={0:F1} dist={1:F1}", RadiansToDegrees(checkFacing), distFromOrigin); countFailToPointNav++; continue; } Vector3 ptNearest = NearestMobLoc(ptDestination, mobLocations); if (ptNearest == Vector3.Zero) { if (furthestNearMobDistSqr < minSafeDistSqr) { furthestNearMobDistSqr = minSafeDistSqr; ptFurthest = ptDestination; // set best available if others fail facingFurthest = checkFacing; } } else { double mobDistSqr = ptDestination.Distance2DSquared(ptNearest); if (furthestNearMobDistSqr < mobDistSqr) { furthestNearMobDistSqr = mobDistSqr; ptFurthest = ptDestination; // set best available if others fail facingFurthest = checkFacing; } if (mobDistSqr <= minSafeDistSqr) { countFailSafe++; continue; } } if (reallyCheckRangeToLineOfSightMob && RangeToLineOfSightMob < ptDestination.Distance(LineOfSightMob.Location) - LineOfSightMob.MeleeDistance()) { countFailRange++; continue; } if (CheckLineOfSightToSafeLocation) { Vector3 ptAdjDest = ptDestination; ptAdjDest.Z += 1f; if (!Styx.WoWInternals.World.GameWorld.IsInLineOfSight(ptAdjOrigin, ptAdjDest)) { // L.debugLog( Color.Cyan, "Mob-free location failed line of sight check for degrees={0:F1} dist={1:F1}", degreesFrom, distFromOrigin); countFailToPointLoS++; continue; } } if (CheckSpellLineOfSightToMob && LineOfSightMob != null) { if (!Styx.WoWInternals.World.GameWorld.IsInLineOfSpellSight(ptDestination, LineOfSightMob.GetTraceLinePos())) { if (!Styx.WoWInternals.World.GameWorld.IsInLineOfSight(ptDestination, LineOfSightMob.GetTraceLinePos())) { // L.debugLog( Color.Cyan, "Mob-free location failed line of sight check for degrees={0:F1} dist={1:F1}", degreesFrom, distFromOrigin); countFailToMobLoS++; continue; } } } L.debugLog("SafeArea: Found mob-free location ({0:F1} yd radius) at degrees={1:F1} dist={2:F1} on point check# {3} at {4}, {5}, {6}", MinSafeDistance, WoWMathHelper.RadiansToDegrees(checkFacing), distFromOrigin, countPointsChecked, ptDestination.X, ptDestination.Y, ptDestination.Z); L.debugLog("SafeArea: processing took {0:F0} ms", (DateTime.UtcNow - startFind).TotalMilliseconds); L.debugLog("SafeArea: meshtrace took {0:F0} ms / fullynav took {1:F0} ms", spanTrace.TotalMilliseconds, spanNav.TotalMilliseconds); L.debugLog("SafeArea: stats for ({0:F1} yd radius) found within {1:F1} yds ({2} checked, {3} nav, {4} not safe, {5} range, {6} pt los, {7} mob los, {8} mesh trace)", MinSafeDistance, MaxScanDistance, countPointsChecked, countFailToPointNav, countFailSafe, countFailRange, countFailToPointLoS, countFailToMobLoS, countFailTrace); return(ptDestination); } } L.debugLog("SafeArea: No mob-free location ({0:F1} yd radius) found within {1:F1} yds ({2} checked, {3} nav, {4} not safe, {5} range, {6} pt los, {7} mob los, {8} mesh trace)", MinSafeDistance, MaxScanDistance, countPointsChecked, countFailToPointNav, countFailSafe, countFailRange, countFailToPointLoS, countFailToMobLoS, countFailTrace); if (ChooseSafestAvailable && ptFurthest != Vector3.Zero) { L.debugLog("SafeArea: choosing best available spot in {0:F1} yd radius where closest mob is {1:F1} yds", MinSafeDistance, Math.Sqrt(furthestNearMobDistSqr)); L.debugLog("SafeArea: processing took {0:F0} ms", (DateTime.UtcNow - startFind).TotalMilliseconds); L.debugLog("SafeArea: meshtrace took {0:F0} ms / fullynav took {1:F0} ms", spanTrace.TotalMilliseconds, spanNav.TotalMilliseconds); return(ChooseSafestAvailable ? ptFurthest : Vector3.Zero); } L.debugLog("SafeArea: processing took {0:F0} ms", (DateTime.UtcNow - startFind).TotalMilliseconds); L.debugLog("SafeArea: meshtrace took {0:F0} ms / fullynav took {1:F0} ms", spanTrace.TotalMilliseconds, spanNav.TotalMilliseconds); return(Vector3.Zero); }
public static Composite CreateDisengageBehavior() { return (new Decorator( ret => IsDisengageNeeded(), new Sequence( new ActionDebugString(ret => "face away from or towards safespot as needed"), new Action(delegate { if (useRocketJump) { needFacing = Styx.Helpers.WoWMathHelper.CalculateNeededFacing(Me.Location, safeSpot); } else { needFacing = Styx.Helpers.WoWMathHelper.CalculateNeededFacing(safeSpot, Me.Location); } needFacing = WoWMathHelper.NormalizeRadian(needFacing); float rotation = WoWMathHelper.NormalizeRadian(Math.Abs(needFacing - Me.RenderFacing)); Logger.Write(Color.Cyan, "DIS: turning {0:F0} degrees {1} safe landing spot", WoWMathHelper.RadiansToDegrees(rotation), useRocketJump ? "towards" : "away from"); Me.SetFacing(needFacing); }), new ActionDebugString(ret => "wait for facing to complete"), new PrioritySelector( new Wait(new TimeSpan(0, 0, 1), ret => Me.IsDirectlyFacing(needFacing), new ActionAlwaysSucceed()), new Action(ret => { Logger.Write(Color.Cyan, "DIS: timed out waiting to face safe spot - need:{0:F4} have:{1:F4}", needFacing, Me.RenderFacing); return RunStatus.Failure; }) ), // stop facing new Action(ret => { Logger.Write(Color.Cyan, "DIS: cancel facing now we point the right way"); WoWMovement.StopFace(); }), new ActionDebugString(ret => "set time of disengage just prior"), new Sequence( new PrioritySelector( new Decorator(ret => !useRocketJump, Spell.BuffSelf("Disengage")), new Decorator(ret => useRocketJump, Spell.BuffSelf("Rocket Jump")), new Action(ret => Logger.Write(Color.Cyan, "DIS: {0} cast appears to have failed", useRocketJump ? "Rocket Jump" : "Disengage")) ), new Action(ret => { NextDisengageAllowed = DateTime.Now.Add(new TimeSpan(0, 0, 0, 0, 750)); Logger.Write(Color.Cyan, "DIS: finished {0} cast", useRocketJump ? "Rocket Jump" : "Disengage"); if (Kite.IsKitingActive()) { Kite.EndKiting(String.Format("BP: Interrupted by {0}", useRocketJump ? "Rocket Jump" : "Disengage")); } return RunStatus.Success; }) ) ) )); }