From d36059e5ce5267111a9bdab0ba6164060c403e8a Mon Sep 17 00:00:00 2001 From: min Date: Sun, 7 Jun 2026 14:01:15 +0300 Subject: [PATCH] =?UTF-8?q?fix(player):=20=D0=BF=D0=BE=D1=80=D1=82=20?= =?UTF-8?q?=E2=80=94=20=D0=B1=D0=BB=D0=B0=D1=81=D1=82=D0=B5=D1=80=20=D0=BE?= =?UTF-8?q?=D1=82=203-=D0=B3=D0=BE=20=D0=BB=D0=B8=D1=86=D0=B0=20=D1=81?= =?UTF-8?q?=D1=82=D1=80=D0=B5=D0=BB=D1=8F=D0=B5=D1=82=20=D0=B2=20=D1=82?= =?UTF-8?q?=D0=BE=D1=87=D0=BA=D1=83=20=D0=BA=D0=BB=D0=B8=D0=BA=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 --- src/engine/WeaponSystem.js | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/src/engine/WeaponSystem.js b/src/engine/WeaponSystem.js index a4bf657..e04a243 100644 --- a/src/engine/WeaponSystem.js +++ b/src/engine/WeaponSystem.js @@ -90,6 +90,17 @@ export class WeaponSystem { if (e.button !== 0) return; // Если UI-режим курсора — не стреляем (мышь работает по GUI) if (this.scene3d?.player?.isUiCursorMode?.()) return; + // Свободный курсор (нет pointer-lock, обычно 3-е лицо) → стрелять туда, + // куда кликнули, а не в центр камеры. + if (document.pointerLockElement !== canvas) { + const rect = canvas.getBoundingClientRect(); + const cx = (e.clientX != null ? e.clientX : 0) - rect.left; + const cy = (e.clientY != null ? e.clientY : 0) - rect.top; + if (cx >= 0 && cy >= 0 && cx <= rect.width && cy <= rect.height) { + this.setAimScreenPoint(cx * (canvas.width / rect.width), + cy * (canvas.height / rect.height)); + } + } this._mouseDown = true; this._tryFire(); }; @@ -97,14 +108,26 @@ export class WeaponSystem { if (e.button !== 0) return; this._mouseDown = false; }; + const onMove = (e) => { + if (!this._mouseDown) return; + if (document.pointerLockElement === canvas) return; + const rect = canvas.getBoundingClientRect(); + const cx = (e.clientX != null ? e.clientX : 0) - rect.left; + const cy = (e.clientY != null ? e.clientY : 0) - rect.top; + if (cx >= 0 && cy >= 0 && cx <= rect.width && cy <= rect.height) { + this._holdAim = { x: cx * (canvas.width / rect.width), y: cy * (canvas.height / rect.height) }; + } + }; const onKey = (e) => { if (e.code === 'KeyR') this.reload(); }; canvas.addEventListener('mousedown', onDown); window.addEventListener('mouseup', onUp); + window.addEventListener('mousemove', onMove); window.addEventListener('keydown', onKey); this._listeners.push({ target: canvas, type: 'mousedown', fn: onDown }); this._listeners.push({ target: window, type: 'mouseup', fn: onUp }); + this._listeners.push({ target: window, type: 'mousemove', fn: onMove }); this._listeners.push({ target: window, type: 'keydown', fn: onKey }); // Регистрируем перед-кадровый хук для авто-стрельбы (если auto=true) @@ -583,7 +606,10 @@ export class WeaponSystem { // (для tap-to-shoot на мобиле). Точка применяется один раз. let hit = null; let ray; - const aim = this._aimScreenPoint; + let aim = this._aimScreenPoint; + if (!aim && this._holdAim && document.pointerLockElement !== this.scene3d?.canvas) { + aim = this._holdAim; + } try { if (aim) { ray = this.scene.createPickingRay(aim.x, aim.y, null, camera);