// Own objective locations are doctrine, not enemy observations. A straight-line // heading suggests a destination; it does not assert a road route or player goal. class ERR_HQDoctrine { static float Threat(vector objective, vector lastSeen, vector velocity, bool heading, float confidence, float radius) { if (!ERR_HQPursuitRules.PositionValid(objective) || !ERR_HQPursuitRules.PositionValid(lastSeen)) return 0; float standing = 0.2; if (!ERR_HQPursuitRules.Finite(confidence) || confidence < 0 || confidence > 1 || !ERR_HQPursuitRules.Finite(radius) || radius < 0 || radius > 2000) return standing; vector route = objective - lastSeen; route[1] = 0; float distance = route.Length(); float proximity = 1 / (1 + distance / Math.Max(100, radius)); float alignment; if (distance > 1 && ERR_HQPursuitRules.Heading(velocity, heading)) alignment = Math.Max(0, vector.Dot(route.Normalized(), ERR_HQPursuitRules.Direction(velocity, true))); return standing + confidence * (0.4 * proximity + 0.6 * alignment / (1 + distance / 3000)); } static bool Forward(vector objective, vector position, vector velocity, bool heading) { if (!ERR_HQPursuitRules.PositionValid(objective) || !ERR_HQPursuitRules.PositionValid(position) || !ERR_HQPursuitRules.Heading(velocity, heading)) return false; vector route = objective - position; route[1] = 0; return route.Length() >= 150 && vector.Dot(route.Normalized(), ERR_HQPursuitRules.Direction(velocity, true)) >= 0.5; } static vector Approach(vector objective, vector position) { vector route = objective - position; route[1] = 0; if (route.Length() < 1) return position; return position + route.Normalized() * Math.Clamp(route.Length() * 0.25, 100, 200); } }