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;
}