/**
 * Простейшие проверки фигур боя (перенос v1): круг и конус удара.
 * v2-отличие: конус меряется прямо в мировых горизонтальных осях (x/z) —
 * воксели кубические, анизотропной изо-проекции v1 нет (урок №1: всё в
 * мировом пространстве, проекция — только на границе рендера).
 */

/** Горизонтальный вектор/точка мира (бой живёт в плоскости x/z). */
export interface Hor {
    x: number;
    z: number;
}

/** Дистанция между точками в горизонтальной плоскости. */
export function horDist(a: Hor, b: Hor): number {
    return Math.hypot(b.x - a.x, b.z - a.z);
}

/** Нормализованный вектор из a в b (нулевая дистанция — (0,0)). */
export function horNorm(a: Hor, b: Hor): Hor {
    const dx = b.x - a.x;
    const dz = b.z - a.z;
    const d = Math.hypot(dx, dz);
    return d < 1e-9 ? { x: 0, z: 0 } : { x: dx / d, z: dz / d };
}

/** Точка внутри круга (включая границу). */
export function inCircle(center: Hor, radius: number, point: Hor): boolean {
    const dx = point.x - center.x;
    const dz = point.z - center.z;
    return dx * dx + dz * dz <= radius * radius;
}

/** Угол между векторами a и b (радианы, 0..PI). */
export function angleBetween(a: Hor, b: Hor): number {
    const la = Math.hypot(a.x, a.z);
    const lb = Math.hypot(b.x, b.z);
    if (la === 0 || lb === 0) return 0;
    let cos = (a.x * b.x + a.z * b.z) / (la * lb);
    cos = Math.min(1, Math.max(-1, cos));
    return Math.acos(cos);
}

/**
 * Точка внутри конуса: в пределах range от from и угол до dir не больше halfAngle.
 * Нулевое направление — конус «схлопывается» в круг по range (угол не проверяется).
 */
export function inCone(from: Hor, dir: Hor, range: number, halfAngle: number, point: Hor): boolean {
    const dx = point.x - from.x;
    const dz = point.z - from.z;
    if (dx * dx + dz * dz > range * range) return false;
    if (dir.x === 0 && dir.z === 0) return true;
    return angleBetween(dir, { x: dx, z: dz }) <= halfAngle;
}