RayMelius Claude Opus 4.6 commited on
Commit
f3c37b8
·
1 Parent(s): d7953c9

FPV chat: add proximity fallback when raycaster misses agents

Browse files
Files changed (1) hide show
  1. web/3d.html +34 -1
web/3d.html CHANGED
@@ -3301,7 +3301,10 @@ const _interactRay = new THREE.Raycaster();
3301
  _interactRay.far = 15;
3302
  function updateInteractPrompt() {
3303
  const prompt = document.getElementById('fp-interact-prompt');
3304
- if (chatTargetId || !fpControls.isLocked) { prompt.style.display = 'none'; return; }
 
 
 
3305
  _interactRay.setFromCamera(new THREE.Vector2(0, 0), fpCamera);
3306
  const objs = [];
3307
  for (const [, m] of agentMeshes) objs.push(m);
@@ -3316,6 +3319,21 @@ function updateInteractPrompt() {
3316
  return;
3317
  }
3318
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3319
  prompt.style.display = 'none';
3320
  }
3321
 
@@ -3621,6 +3639,17 @@ let chatMessages = [];
3621
  let speechRecognition = null;
3622
  let isRecording = false;
3623
 
 
 
 
 
 
 
 
 
 
 
 
3624
  function fpInteract() {
3625
  if (!fpMode) return;
3626
  if (chatTargetId) { endNpcChat(); return; }
@@ -3641,6 +3670,10 @@ function fpInteract() {
3641
  }
3642
  }
3643
 
 
 
 
 
3644
  const bldgObjs = [];
3645
  for (const [, m] of buildingMeshes) bldgObjs.push(m);
3646
  const bHits = ray.intersectObjects(bldgObjs, true);
 
3301
  _interactRay.far = 15;
3302
  function updateInteractPrompt() {
3303
  const prompt = document.getElementById('fp-interact-prompt');
3304
+ if (chatTargetId) { prompt.style.display = 'none'; return; }
3305
+ if (!fpControls.isLocked) { prompt.style.display = 'none'; return; }
3306
+
3307
+ // Try raycaster first
3308
  _interactRay.setFromCamera(new THREE.Vector2(0, 0), fpCamera);
3309
  const objs = [];
3310
  for (const [, m] of agentMeshes) objs.push(m);
 
3319
  return;
3320
  }
3321
  }
3322
+
3323
+ // Fallback: proximity check
3324
+ let best = null, bestDist = 6;
3325
+ const cam = fpCamera.position;
3326
+ for (const [id, m] of agentMeshes) {
3327
+ if (id === 'player') continue;
3328
+ const d = cam.distanceTo(m.position);
3329
+ if (d < bestDist) { bestDist = d; best = m; }
3330
+ }
3331
+ if (best) {
3332
+ const name = best.userData.data?.name || best.userData.id;
3333
+ prompt.innerHTML = `Press <b>E</b> to talk to <b>${name}</b>`;
3334
+ prompt.style.display = 'block';
3335
+ return;
3336
+ }
3337
  prompt.style.display = 'none';
3338
  }
3339
 
 
3639
  let speechRecognition = null;
3640
  let isRecording = false;
3641
 
3642
+ function findNearestAgent() {
3643
+ let best = null, bestDist = 6;
3644
+ const cam = fpCamera.position;
3645
+ for (const [id, m] of agentMeshes) {
3646
+ if (id === 'player') continue;
3647
+ const d = cam.distanceTo(m.position);
3648
+ if (d < bestDist) { bestDist = d; best = id; }
3649
+ }
3650
+ return best;
3651
+ }
3652
+
3653
  function fpInteract() {
3654
  if (!fpMode) return;
3655
  if (chatTargetId) { endNpcChat(); return; }
 
3670
  }
3671
  }
3672
 
3673
+ // Fallback: nearest agent within 6 units
3674
+ const nearest = findNearestAgent();
3675
+ if (nearest) { startNpcChat(nearest); return; }
3676
+
3677
  const bldgObjs = [];
3678
  for (const [, m] of buildingMeshes) bldgObjs.push(m);
3679
  const bHits = ray.intersectObjects(bldgObjs, true);