Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 | 2x 30x 30x 2x | /**
* PlayerStateOverlayHtml Component - Unified player state visual indicators
*
* Combines all player state visual effects into a single overlay:
* - Pain vignette
* - Balance indicator
* - Consciousness blur
* - Blood loss warning
* - Stamina warning
*
* @module components/combat/PlayerStateOverlayHtml
* @category Combat UI
* @korean 플레이어상태오버레이
*/
import React from "react";
import { PainVignette } from "../effects/PainVignette";
import { BalanceIndicator } from "../indicators/BalanceIndicator";
import { ConsciousnessBlur } from "../effects/ConsciousnessBlur";
import { BloodLossOverlayHtml } from "../effects/BloodLossOverlayHtml";
import { StaminaWarning } from "../indicators/StaminaWarning";
import type { BalanceState } from "../../../../../types/player-visual";
export interface PlayerStateOverlayProps {
/**
* Current pain level (0-100)
* @korean 통증
*/
readonly pain: number;
/**
* Current balance state
* @korean 균형상태
*/
readonly balanceState: BalanceState;
/**
* Player position ('left' or 'right')
* @korean 플레이어위치
*/
readonly position: "left" | "right";
/**
* Current consciousness level (0-100)
* @korean 의식
*/
readonly consciousness: number;
/**
* Current blood loss (0-100, optional)
* @korean 출혈
*/
readonly bloodLoss?: number;
/**
* Current stamina (0-100)
* @korean 체력
*/
readonly stamina: number;
/**
* Mobile responsive mode
* @korean 모바일여부
*/
readonly isMobile: boolean;
}
/**
* PlayerStateOverlayHtml - Unified visual effects for player state
*
* Combines all player state visual indicators into a single component
* with optimal performance and consistent rendering. All effects use
* smooth 0.5s transitions and are optimized for 60fps.
*
* Optimized with React.memo for performance:
* - Prevents re-renders when props haven't changed
* - Custom comparison function for precise control
* - Reduces DOM updates for 60fps target
*
* @example
* ```tsx
* <PlayerStateOverlayHtml
* pain={65}
* balanceState="SHAKEN"
* position="left"
* consciousness={80}
* bloodLoss={45}
* stamina={15}
* isMobile={false}
* />
* ```
*/
export const PlayerStateOverlayHtml = React.memo<PlayerStateOverlayProps>(
({
pain,
balanceState,
position,
consciousness,
bloodLoss = 0,
stamina,
isMobile,
}) => {
return (
<>
{/* Pain vignette - shows when pain >= 5 (see PainVignette.tsx) */}
<PainVignette pain={pain} isMobile={isMobile} />
{/* Balance indicator - always visible, color-coded by state (see BalanceIndicator.tsx) */}
<BalanceIndicator
balanceState={balanceState}
position={position}
isMobile={isMobile}
/>
{/* Consciousness blur - shows when consciousness <= 90 (see ConsciousnessBlur.tsx) */}
<ConsciousnessBlur consciousness={consciousness} isMobile={isMobile} />
{/* Blood loss warning - pulses when bloodLoss >= 50 (see BloodLossOverlayHtml.tsx) */}
<BloodLossOverlayHtml bloodLoss={bloodLoss} isMobile={isMobile} />
{/* Stamina warning - flashes when stamina < 20 (see StaminaWarning.tsx) */}
<StaminaWarning stamina={stamina} isMobile={isMobile} />
</>
);
},
(prevProps, nextProps) => {
// Custom comparison for optimal re-render prevention
// Only re-render if any state value actually changed
return (
prevProps.pain === nextProps.pain &&
prevProps.balanceState === nextProps.balanceState &&
prevProps.position === nextProps.position &&
prevProps.consciousness === nextProps.consciousness &&
prevProps.bloodLoss === nextProps.bloodLoss &&
prevProps.stamina === nextProps.stamina &&
prevProps.isMobile === nextProps.isMobile
);
},
);
PlayerStateOverlayHtml.displayName = "PlayerStateOverlayHtml";
|