Client only. Server validates synced cursor position.
If looking upward/horizontal, we are probably not aiming at a pond surface.
The ray is close enough to the liquid surface.
Last chance: use closest sampled surface if it was very close.
432 {
433 #ifdef DIAG_DEVELOPER
434 float debugBestDelta = 999999.0;
435 int debugSampleCount = 0;
436 int debugValidKnownSurfaceCount = 0;
437 string debugPondFailReason = "no pond samples";
438 #endif
439
440 pondHitPosition = vector.Zero;
441
443 if (
g_Game.IsHeadlessOrDedicatedServer())
444 return false;
445
446 vector cameraPos =
g_Game.GetCurrentCameraPosition();
447 vector cameraDir =
g_Game.GetCurrentCameraDirection();
448
449 if (cameraPos == vector.Zero || cameraDir == vector.Zero)
450 return false;
451
453
455 if (cameraDir[1] > 0.15)
456 return false;
457
459 if (safeDistance <= 1.0)
461
462 vector bestSurfacePos = vector.Zero;
464 float bestDelta = 999999.0;
465 vector pondSurfacePos = vector.Zero;
466
468 {
469 #ifdef DIAG_DEVELOPER
470 debugSampleCount++;
471 #endif
472
473 vector probePos = cameraPos + cameraDir * dist;
474
475 vector surfacePos;
476 int liquidType;
477 string surfaceType;
478
480 {
481 #ifdef DIAG_DEVELOPER
482 debugPondFailReason = "TryGetLiquidSurfaceAt failed";
483 #endif
484 continue;
485 }
486
488 {
489 #ifdef DIAG_DEVELOPER
490 debugPondFailReason = "known pond surface invalid";
491 #endif
492 continue;
493 }
494
495 #ifdef DIAG_DEVELOPER
496 debugValidKnownSurfaceCount++;
497 #endif
498
499 float rayToSurfaceDelta = Math.AbsFloat(probePos[1] - surfacePos[1]);
500 if (rayToSurfaceDelta < bestDelta)
501 {
502 bestDelta = rayToSurfaceDelta;
503 bestSurfacePos = surfacePos;
504 bestLiquidType = liquidType;
505
506 #ifdef DIAG_DEVELOPER
507 debugBestDelta = bestDelta;
508 debugPondFailReason = "best pond surface too far from camera ray";
509 #endif
510 }
511
514 {
516
518 continue;
519
520 pondSurfacePos = surfacePos;
522
524 continue;
525
526 pondHitPosition = surfacePos;
527 return true;
528 }
529 }
530
533 {
536 {
537 pondSurfacePos = bestSurfacePos;
539
541 return false;
542
543 pondHitPosition = bestSurfacePos;
544 return true;
545 }
546 }
547
548 #ifdef DIAG_DEVELOPER
549 DbgUI.Begin("", 50, 240);
550 if (m_DebugSyntheticCursor)
551 {
553 }
554 DbgUI.End();
555 #endif
556
557 return false;
558 }
bool HasClearPathToLiquidSurface(PlayerBase player, vector surfacePos)
bool IsNearlyZero(vector value)
bool IsValidPondHitPosition(vector playerPos, vector hitPosition, int liquidType=LIQUID_NONE)
vector ApplySyntheticHitCursorStability(vector playerPos, vector candidate, int liquidType)
bool TryGetLiquidSurfaceAt(vector probePosition, out vector surfacePosition, out int liquidType, out string surfaceType)
static const float SYNTHETIC_POND_FALLBACK_SURFACE_TOLERANCE
static const float SYNTHETIC_CURSOR_DISTANCE_BUFFER
bool IsAllowedPondLiquidSurface(vector playerPos, vector surfacePos, int liquidType)
float m_MaxActionDistance
static const float SYNTHETIC_POND_SAMPLE_STEP
static const float LIQUID_SURFACE_RAYCAST_OFFSET
static const float SYNTHETIC_POND_SURFACE_TOLERANCE
proto float Normalize()
Normalizes vector. Returns length.