// Frostcall Arena (25 Oct 2026): exact World of Warcraft controls, excerpts from src/game/Game.ts (read, adapt, never import).
// 1. mouse: left drag = camera only, right drag = steer the hero, both buttons = run forward (chorded buttons via e.buttons),
//    a short right click = target the enemy under the cursor, else walk to the ground point.
    const down = (e: PointerEvent) => {
      if (this.state !== "playing") return;
      if (e.pointerType === "touch") return;
      c.setPointerCapture?.(e.pointerId);
      if (e.button === 2) {
        this.rmb = true;
        this.downAt2 = { x: e.clientX, y: e.clientY, t: performance.now() };
      }
      if (e.button === 0) {
        this.lmb = true;
        this.downAt = { x: e.clientX, y: e.clientY, t: performance.now() };
      }
      this.drive.dragging = true;
    };
    const move = (e: PointerEvent) => {
      if (this.state !== "playing" || e.pointerType === "touch") return;
      // a second button pressed or released while the first is held sends no pointerdown/up, only this move
      // (chorded buttons): read the mask so "both buttons = run forward" works like WoW. No click from a chord.
      const l = (e.buttons & 1) !== 0, r = (e.buttons & 2) !== 0;
      if (l !== this.lmb || r !== this.rmb) {
        this.downAt = this.downAt2 = null;
        this.lmb = l;
        this.rmb = r;
        this.drive.dragging = l || r;
      }
      if (this.rmb) this.drive.look(e.movementX, e.movementY, true);
      else if (this.lmb) this.drive.look(e.movementX, e.movementY, false);
    };
    const up = (e: PointerEvent) => {
      if (e.pointerType === "touch") return;
      if (e.button === 2) {
        this.rmb = false;
        const d = this.downAt2;
        this.downAt2 = null;
        // a right CLICK (no drag): cancels the aiming, else targets the enemy under the mouse; a drag keeps looking
        if (d && Math.hypot(e.clientX - d.x, e.clientY - d.y) < 6 && performance.now() - d.t < 450 && this.state === "playing") {
          if (this.aim) this.cancelAim();
          else if (!this.pickEnemy(e.clientX, e.clientY)) this.moveToward(e.clientX, e.clientY);
        }
      }
      if (e.button === 0) {
        this.lmb = false;
        const d = this.downAt;
        this.downAt = null;
        if (d && Math.hypot(e.clientX - d.x, e.clientY - d.y) < 6 && performance.now() - d.t < 450 && this.state === "playing") this.tapAt(e.clientX, e.clientY);
      }
      this.drive.dragging = this.rmb || this.lmb;
    };
    c.addEventListener("pointerdown", down);
    c.addEventListener("pointermove", move);
    c.addEventListener("pointerup", up);
    c.addEventListener("pointercancel", up);
    c.addEventListener("contextmenu", (e) => e.preventDefault());

// 2. keys: W/S (Z/S) forward/back, A/D (Q/D) STRAFE, arrows turn; click-to-move steering.
  /** WoW keys: W / S (Z / S on AZERTY) forward and back, A / D (Q / D) STRAFE, arrows Left / Right turn.
   *  Mouse: left drag turns the camera only, right drag turns the hero with it, both buttons held run forward. */
  private readMove(dt: number) {
    const k = this.keys;
    let f = (k.has("KeyW") || k.has("ArrowUp") ? 1 : 0) - (k.has("KeyS") || k.has("ArrowDown") ? 1 : 0);
    let strafe = (k.has("KeyD") ? 1 : 0) - (k.has("KeyA") ? 1 : 0);
    let turn = (k.has("ArrowRight") ? 1 : 0) - (k.has("ArrowLeft") ? 1 : 0);
    const run = true; // like WoW the hero always runs at full speed; Shift is the dash
    if (this.lmb && this.rmb) f = 1;
    if (this.stick.x || this.stick.y) {
      f += this.stick.y;
      strafe += this.stick.x;
    }
    if (f || strafe || turn) this.moveTo = null;
    const m = this.moveTo;
    if (m) {
      const p = this.sim.player;
      const dx = m.x - p.x, dz = m.z - p.z, dist = Math.hypot(dx, dz);
      m.t += dt;
      if (dist < m.best - 0.05) {
        m.best = dist;
        m.t = 0;
      }
      if (dist < 0.5 || m.t > 0.6) this.moveTo = null;
      else {
        this.drive.heading = turnToward(this.drive.heading, Math.atan2(dx, dz), 12 * dt);
        f = 1;
      }
    }
    f = Math.max(-1, Math.min(1, f));
    strafe = Math.max(-1, Math.min(1, strafe));
    turn = Math.max(-1, Math.min(1, turn));
    return { f, turn, strafe, run };
  }

