示例#1
0
        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);
        }
        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);
        }
示例#3
0
        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);
        }
示例#4
0
        internal static bool TestLineOfSight(C_WoWObject obj)
        {
            if (obj.LineofsightResult && obj.Distance <= obj.InteractRange)
            {
                return(true);
            }

            if (!obj._lineofSightWaitTimer.IsFinished && (obj.Distance > 30f || obj.LineofSightWaitTimer.TimeLeft.TotalMilliseconds > 750))
            {
                return(obj.LineofsightResult);
            }


            var neededFacing = WoWMathHelper.CalculateNeededFacing(Character.Player.Location, obj.Location);

            var testPoints = new List <WoWPoint>
            {
                WoWMathHelper.GetPointAt(obj.Location, obj.InteractRange, neededFacing - 3.141593f, 0f),
                WoWMathHelper.GetPointAt(obj.Location, obj.InteractRange, neededFacing - 2.356194f, 0f),
                WoWMathHelper.GetPointAt(obj.Location, obj.InteractRange, neededFacing - 1.570796f, 0f),
                WoWMathHelper.GetPointAt(obj.Location, obj.InteractRange, neededFacing - 0.7853982f, 0f),
                WoWMathHelper.GetPointAt(obj.Location, obj.InteractRange, neededFacing, 0f),
                WoWMathHelper.GetPointAt(obj.Location, obj.InteractRange, neededFacing + 3.141593f, 0f),
                WoWMathHelper.GetPointAt(obj.Location, obj.InteractRange, neededFacing + 2.356194f, 0f),
                WoWMathHelper.GetPointAt(obj.Location, obj.InteractRange, neededFacing + 1.570796f, 0f),
                WoWMathHelper.GetPointAt(obj.Location, obj.InteractRange, neededFacing + 0.7853982f, 0f)
            };

            foreach (var testPoint in testPoints)
            {
                if (GameWorld.IsInLineOfSight(Character.Player.TraceLinePosition, testPoint.Add(0f, 0f, 1.24f)))
                {
                    obj.LineofsightResult = true;
                    obj._lineofsightPoint = testPoint;
                    break;
                }
            }


            obj.LineofSightWaitTimer.Reset();
            return(obj.LineofsightResult);
        }
        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));
        }
示例#6
0
        // 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);
        }
示例#7
0
        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;
            }))
                                                                        ))
                                                      )));
        }
示例#8
0
        private static async Task <bool> TrappingBehavior(bool inCombat)
        {
            if (TargetManager.CombatType != TargetManager.CombatFlags.Trapping ||
                !TargetManager.CombatObject.Trappable)
            {
                return(false);
            }


            bool withinTrapDistance = TargetManager.CombatObject.Distance <= TargetManager.PullDistance;
            var  traps = nearbyTraps;

            if (traps.Count == 0 && withinTrapDistance)
            {
                if (Player.Inventory.Trap != null)
                {
                    if (Player.Inventory.Trap.ref_WoWItem.Usable &&
                        !Player.Inventory.Trap.OnCooldown)
                    {
                        TreeRoot.StatusText = "Trapping Behavior";
                        Player.Inventory.Trap.Use();
                        await CommonCoroutines.SleepForRandomUiInteractionTime();

                        return(true);
                    }
                }
            }

            if (inCombat)
            {
                TreeRoot.StatusText = "Trapping Behavior";

                //We want to move the target to our trap..
                //  -If we don't have aggro than we should move to the target
                //  -Else we should wait near our trap.

                if (!TargetManager.CombatObject.IsTargetingMe)
                {
                    //Wait for movement..
                    if (!withinTrapDistance)
                    {
                        return(false);
                    }
                }
                else
                {
                    //Move to nearest trap..
                    if (traps.Count > 0)
                    {
                        var nearestTrap = traps[0];
                        var distance    = nearestTrap.Location.Distance(TargetManager.CombatObject.Location);
                        if (distance > 1.5f || _trapMovement == null)
                        {
                            if (_trapMovement == null || _trapMovement.CurrentMovementQueue.Count == 0)
                            {
                                //Get the current side facing flipped!
                                float requiredFacingDegrees = WoWMathHelper.RadiansToDegrees(
                                    WoWMathHelper.CalculateNeededFacing(
                                        TargetManager.CombatObject.Location, nearestTrap.Location));



                                _trapMovement =
                                    new Movement(
                                        nearestTrap.GetSidePoint(requiredFacingDegrees, 8f),
                                        5f,
                                        "Trap Point");
                            }


                            if (_trapMovement != null)
                            {
                                await _trapMovement.MoveTo();
                            }
                            return(true);
                        }
                    }
                }
            }
            else if (withinTrapDistance) //Not in Combat
            {
                if (RoutineManager.Current.CombatBehavior != null &&
                    await RoutineManager.Current.CombatBehavior.ExecuteCoroutine())
                {
                    TreeRoot.StatusText = "Combat Behavior";
                    return(true);
                }
            }

            return(false);
        }
示例#9
0
        public static Composite CreateHolyHealOnlyBehavior(bool selfOnly, bool moveInRange)
        {
            // Atonement - Tab 1  index 10 - 1/2 pts
            HealerManager.NeedHealTargeting = true;
            return(new
                   PrioritySelector(
                       ret => selfOnly ? StyxWoW.Me : HealerManager.Instance.FirstUnit,
                       new Decorator(
                           ret => ret != null && (moveInRange || ((WoWUnit)ret).InLineOfSpellSight && ((WoWUnit)ret).DistanceSqr < 40 * 40),
                           new PrioritySelector(
                               Spell.WaitForCast(),
                               new Decorator(
                                   ret => moveInRange,
                                   Movement.CreateMoveToLosBehavior(ret => (WoWUnit)ret)),

                               Spell.Cast("Shadowfiend", ret => StyxWoW.Me.ManaPercent <= 80 && StyxWoW.Me.GotTarget),

                               Spell.BuffSelf("Desperate Prayer", ret => StyxWoW.Me.HealthPercent <= 50),
                               Spell.BuffSelf("Hymn of Hope", ret => StyxWoW.Me.ManaPercent <= 15 && (!SpellManager.HasSpell("Shadowfiend") || SpellManager.Spells["Shadowfiend"].Cooldown)),
                               Spell.BuffSelf("Divine Hymn", ret => Unit.NearbyFriendlyPlayers.Count(p => p.HealthPercent <= SingularSettings.Instance.Priest.DivineHymnHealth) >= SingularSettings.Instance.Priest.DivineHymnCount),

                               Spell.BuffSelf("Chakra"),
                               Spell.Cast(
                                   "Prayer of Mending",
                                   ret => (WoWUnit)ret,
                                   ret => ret is WoWPlayer && Group.Tanks.Contains((WoWPlayer)ret) && !((WoWUnit)ret).HasMyAura("Prayer of Mending", 3) &&
                                   Group.Tanks.Where(t => t != (WoWPlayer)ret).All(p => !p.HasMyAura("Prayer of Mending"))),
                               Spell.Heal(
                                   "Renew",
                                   ret => (WoWUnit)ret,
                                   ret => ret is WoWPlayer && Group.Tanks.Contains((WoWPlayer)ret) && !((WoWUnit)ret).HasMyAura("Renew")),
                               Spell.Heal("Prayer of Healing",
                                          ret => (WoWUnit)ret,
                                          ret => StyxWoW.Me.HasAura("Serendipity", 2) && Unit.NearbyFriendlyPlayers.Count(p => p.HealthPercent <= SingularSettings.Instance.Priest.PrayerOfHealingSerendipityHealth) >= SingularSettings.Instance.Priest.PrayerOfHealingSerendipityCount),
                               Spell.Heal("Circle of Healing",
                                          ret => (WoWUnit)ret,
                                          ret => Unit.NearbyFriendlyPlayers.Count(p => p.HealthPercent <= SingularSettings.Instance.Priest.CircleOfHealingHealth) >= SingularSettings.Instance.Priest.CircleOfHealingCount),
                               Spell.CastOnGround(
                                   "Holy Word: Sanctuary",
                                   ret => Clusters.GetBestUnitForCluster(Unit.NearbyFriendlyPlayers.Select(p => p.ToUnit()), ClusterType.Radius, 10f).Location,
                                   ret => Clusters.GetClusterCount((WoWUnit)ret, Unit.NearbyFriendlyPlayers.Select(p => p.ToUnit()), ClusterType.Radius, 10f) >= 4),
                               Spell.Heal(
                                   "Holy Word: Serenity",
                                   ret => (WoWUnit)ret,
                                   ret => ret is WoWPlayer && Group.Tanks.Contains((WoWPlayer)ret)),

                               Spell.Buff("Guardian Spirit",
                                          ret => (WoWUnit)ret,
                                          ret => ((WoWUnit)ret).HealthPercent <= 10),

                               Spell.CastOnGround("Lightwell", ret => StyxWoW.Me.Location.RayCast(WoWMathHelper.CalculateNeededFacing(StyxWoW.Me.Location, ((WoWUnit)ret).Location), 15f)),
                               Spell.Heal(
                                   "Flash Heal",
                                   ret => (WoWUnit)ret,
                                   ret => StyxWoW.Me.HasAura("Surge of Light") && ((WoWUnit)ret).HealthPercent <= 90),
                               Spell.Heal(
                                   "Flash Heal",
                                   ret => (WoWUnit)ret,
                                   ret => ((WoWUnit)ret).HealthPercent < SingularSettings.Instance.Priest.HolyFlashHeal),
                               Spell.Heal(
                                   "Greater Heal",
                                   ret => (WoWUnit)ret,
                                   ret => ((WoWUnit)ret).HealthPercent < SingularSettings.Instance.Priest.HolyGreaterHeal),
                               Spell.Heal(
                                   "Heal",
                                   ret => (WoWUnit)ret,
                                   ret => ((WoWUnit)ret).HealthPercent < SingularSettings.Instance.Priest.HolyHeal),
                               new Decorator(
                                   ret => StyxWoW.Me.Combat && StyxWoW.Me.GotTarget && Unit.NearbyFriendlyPlayers.Count(u => u.IsInMyPartyOrRaid) == 0,
                                   new PrioritySelector(
                                       Movement.CreateMoveToLosBehavior(),
                                       Movement.CreateFaceTargetBehavior(),
                                       Helpers.Common.CreateInterruptSpellCast(ret => StyxWoW.Me.CurrentTarget),
                                       Spell.Buff("Shadow Word: Pain", true),
                                       Spell.Cast("Holy Word: Chastise"),
                                       Spell.Cast("Holy Fire"),
                                       Spell.Cast("Smite"),
                                       Movement.CreateMoveToTargetBehavior(true, 35f)
                                       )),
                               new Decorator(
                                   ret => moveInRange,
                                   Movement.CreateMoveToTargetBehavior(true, 35f, ret => (WoWUnit)ret))

                               // Divine Hymn
                               // Desperate Prayer
                               // Prayer of Mending
                               // Prayer of Healing
                               // Power Word: Barrier
                               // TODO: Add smite healing. Only if Atonement is talented. (Its useless otherwise)
                               ))));
        }