fBaseXtensions.Navigation.Navigation.FindZigZagTargetLocation C# (CSharp) Method

FindZigZagTargetLocation() public method

public FindZigZagTargetLocation ( System.Vector3 vTargetLocation, float fDistanceOutreach, bool bRandomizeDistance = false, bool bRandomizeStart = false ) : System.Vector3
vTargetLocation System.Vector3
fDistanceOutreach float
bRandomizeDistance bool
bRandomizeStart bool
return System.Vector3
        public Vector3 FindZigZagTargetLocation(Vector3 vTargetLocation, float fDistanceOutreach, bool bRandomizeDistance = false, bool bRandomizeStart = false)
        {
            var rndNum = new Random(int.Parse(Guid.NewGuid().ToString().Substring(0, 8), NumberStyles.HexNumber));
            float iFakeStart = 0;
            //K: bRandomizeStart is for boss and elite, they usually jump around, make obstacles, let you Incapacitated.
            //   you usually have to move back and forth to hit them
            if (bRandomizeStart)
                iFakeStart = rndNum.Next(18) * 5;
            if (bRandomizeDistance)
                fDistanceOutreach += rndNum.Next(18);
            float fDirectionToTarget = FindDirection(FunkyGame.Hero.Position, vTargetLocation);

            float fHighestWeight = float.NegativeInfinity;
            Vector3 vBestLocation = Vector3.Zero;

            bool bFoundSafeSpotsFirstLoop = false;
            float fAdditionalRange = 0f;
            //K: Direction is more important than distance

            for (int iMultiplier = 1; iMultiplier <= 2; iMultiplier++)
            {
                if (iMultiplier == 2)
                {
                    if (bFoundSafeSpotsFirstLoop)
                        break;
                    fAdditionalRange = 150f;
                    if (bRandomizeStart)
                        iFakeStart = 30f + (rndNum.Next(16) * 5);
                    else
                        iFakeStart = (rndNum.Next(17) * 5);
                }
                float fRunDistance = fDistanceOutreach;
                for (float iDegreeChange = iFakeStart; iDegreeChange <= 30f + fAdditionalRange; iDegreeChange += 5)
                {
                    float iPosition = iDegreeChange;
                    //point to target is better, otherwise we have to avoid obstacle first
                    if (iPosition > 105f)
                        iPosition = 90f - iPosition;
                    else if (iPosition > 30f)
                        iPosition -= 15f;
                    else
                        iPosition = 15f - iPosition;
                    float fPointToTarget = iPosition;

                    iPosition += fDirectionToTarget;
                    if (iPosition < 0)
                        iPosition = 360f + iPosition;
                    if (iPosition >= 360f)
                        iPosition = iPosition - 360f;

                    Vector3 vThisZigZag = MathEx.GetPointAt(FunkyGame.Hero.Position, fRunDistance, MathEx.ToRadians(iPosition));

                    if (fPointToTarget <= 30f || fPointToTarget >= 330f)
                    {
                        vThisZigZag.Z = vTargetLocation.Z;
                    }
                    else if (fPointToTarget <= 60f || fPointToTarget >= 300f)
                    {
                        //K: we are trying to find position that we can circle around the target
                        //   but we shouldn't run too far away from target
                        vThisZigZag.Z = (vTargetLocation.Z + FunkyGame.Hero.Position.Z) / 2;
                        fRunDistance = fDistanceOutreach - 5f;
                    }
                    else
                    {
                        //K: don't move too far if we are not point to target, we just try to move
                        //   this can help a lot when we are near stairs
                        fRunDistance = 8f;
                    }

                    bool bCanRayCast = MGP.CanStandAt(vThisZigZag);

                    // Give weight to each zigzag point, so we can find the best one to aim for
                    if (bCanRayCast)
                    {
                        const bool bAnyAvoidance = false;

                        // Starting weight is 1000f
                        float fThisWeight = 1000f;
                        if (iMultiplier == 2)
                            fThisWeight -= 80f;

                        //FLEEING
                        //if (Targeting.Behaviors.TBFleeing.ShouldFlee && ObjectCache.Objects.IsPointNearbyMonsters(vThisZigZag, FunkyBaseExtension.Settings.Fleeing.FleeMaxMonsterDistance))
                        //	continue;

                        if (ObjectCache.Obstacles.Navigations.Any(obj => obj.Obstacletype.Value != ObstacleType.Monster && obj.TestIntersection(FunkyGame.Hero.Position, vThisZigZag, false)))
                            continue;

                        float distanceToTarget = vTargetLocation.Distance2D(FunkyGame.Hero.Position);

                        fThisWeight += (distanceToTarget * 10f);

                        // Use this one if it's more weight, or we haven't even found one yet, or if same weight as another with a random chance
                        if (fThisWeight > fHighestWeight)
                        {
                            fHighestWeight = fThisWeight;

                            vBestLocation = new Vector3(vThisZigZag.X, vThisZigZag.Y, MGP.GetHeight(vThisZigZag.ToVector2()));

                            if (!bAnyAvoidance)
                                bFoundSafeSpotsFirstLoop = true;
                        }
                    }
                    // Can we raycast to the point at minimum?
                }
                // Loop through degrees
            }
            // Loop through multiplier
            return vBestLocation;
        }