blacktrigram 0.7.47 → 0.7.49

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (471) hide show
  1. package/lib/App2.js.map +1 -1
  2. package/lib/audio/AudioAssetLoader.js.map +1 -1
  3. package/lib/audio/AudioAssetRegistry.js.map +1 -1
  4. package/lib/audio/AudioCache.js.map +1 -1
  5. package/lib/audio/AudioManager.js.map +1 -1
  6. package/lib/audio/AudioMonitor.js.map +1 -1
  7. package/lib/audio/AudioPool.js.map +1 -1
  8. package/lib/audio/AudioProvider.js.map +1 -1
  9. package/lib/audio/AudioUtils.js.map +1 -1
  10. package/lib/audio/BoneImpactAudioMap.js.map +1 -1
  11. package/lib/audio/VariantSelector.js.map +1 -1
  12. package/lib/audio/types.js.map +1 -1
  13. package/lib/components/screens/combat/CombatScreen3D.d.ts.map +1 -1
  14. package/lib/components/screens/combat/CombatScreen3D.js +29 -25
  15. package/lib/components/screens/combat/CombatScreen3D.js.map +1 -1
  16. package/lib/components/screens/combat/components/controls/CombatButtons.js.map +1 -1
  17. package/lib/components/screens/combat/components/controls/CombatControlsPanel.js.map +1 -1
  18. package/lib/components/screens/combat/components/controls/ControlsGuide.js.map +1 -1
  19. package/lib/components/screens/combat/components/controls/KeyboardHints.js.map +1 -1
  20. package/lib/components/screens/combat/components/controls/PauseMenu.js.map +1 -1
  21. package/lib/components/screens/combat/components/controls/PauseMenuButton.js.map +1 -1
  22. package/lib/components/screens/combat/components/controls/QuickSettings.js.map +1 -1
  23. package/lib/components/screens/combat/components/effects/BloodDecals3D.js.map +1 -1
  24. package/lib/components/screens/combat/components/effects/BloodLossOverlayHtml.js.map +1 -1
  25. package/lib/components/screens/combat/components/effects/BloodParticles3D.js.map +1 -1
  26. package/lib/components/screens/combat/components/effects/BloodViscosity3D.js.map +1 -1
  27. package/lib/components/screens/combat/components/effects/CombatParticleEffects3D.js.map +1 -1
  28. package/lib/components/screens/combat/components/effects/ConsciousnessBlur.js.map +1 -1
  29. package/lib/components/screens/combat/components/effects/InternalDamage3D.js.map +1 -1
  30. package/lib/components/screens/combat/components/effects/PainVignette.js.map +1 -1
  31. package/lib/components/screens/combat/components/effects/ParticleAudio3D.js.map +1 -1
  32. package/lib/components/screens/combat/components/effects/TraumaOverlay3D.js.map +1 -1
  33. package/lib/components/screens/combat/components/feedback/MatchCountdown.js.map +1 -1
  34. package/lib/components/screens/combat/components/feedback/RoundAnnouncementOverlayHtml.js.map +1 -1
  35. package/lib/components/screens/combat/components/feedback/RoundDisplayStatus.js.map +1 -1
  36. package/lib/components/screens/combat/components/feedback/RoundStartAnnouncementOverlayHtml.js.map +1 -1
  37. package/lib/components/screens/combat/components/hud/CombatBottomHUD.d.ts.map +1 -1
  38. package/lib/components/screens/combat/components/hud/CombatBottomHUD.js +2 -2
  39. package/lib/components/screens/combat/components/hud/CombatBottomHUD.js.map +1 -1
  40. package/lib/components/screens/combat/components/hud/CombatLeftHUD.js.map +1 -1
  41. package/lib/components/screens/combat/components/hud/CombatPortraitStatusStrip.js +1 -1
  42. package/lib/components/screens/combat/components/hud/CombatPortraitStatusStrip.js.map +1 -1
  43. package/lib/components/screens/combat/components/hud/CombatRightHUD.js.map +1 -1
  44. package/lib/components/screens/combat/components/hud/CombatTopHUD.d.ts.map +1 -1
  45. package/lib/components/screens/combat/components/hud/CombatTopHUD.js +2 -1
  46. package/lib/components/screens/combat/components/hud/CombatTopHUD.js.map +1 -1
  47. package/lib/components/screens/combat/components/hud/DifficultyIndicator.js.map +1 -1
  48. package/lib/components/screens/combat/components/hud/FPSMonitor.js.map +1 -1
  49. package/lib/components/screens/combat/components/hud/MobileControlsWrapper.js.map +1 -1
  50. package/lib/components/screens/combat/components/hud/PlayerStateOverlayHtml.js.map +1 -1
  51. package/lib/components/screens/combat/components/indicators/BalanceIndicator.js.map +1 -1
  52. package/lib/components/screens/combat/components/indicators/InputBufferDisplay.js.map +1 -1
  53. package/lib/components/screens/combat/components/indicators/StaminaWarning.js.map +1 -1
  54. package/lib/components/screens/combat/components/indicators/TechniqueNameDisplay.js.map +1 -1
  55. package/lib/components/screens/combat/helpers/AnimationUpdater.d.ts.map +1 -1
  56. package/lib/components/screens/combat/helpers/AnimationUpdater.js +4 -2
  57. package/lib/components/screens/combat/helpers/AnimationUpdater.js.map +1 -1
  58. package/lib/components/screens/combat/helpers/combatHelpers.js.map +1 -1
  59. package/lib/components/screens/combat/hooks/useAICombat.js.map +1 -1
  60. package/lib/components/screens/combat/hooks/useCombatActions.js.map +1 -1
  61. package/lib/components/screens/combat/hooks/useCombatAttackMovement.js.map +1 -1
  62. package/lib/components/screens/combat/hooks/useCombatAudio.js.map +1 -1
  63. package/lib/components/screens/combat/hooks/useCombatLayout.d.ts.map +1 -1
  64. package/lib/components/screens/combat/hooks/useCombatLayout.js +11 -5
  65. package/lib/components/screens/combat/hooks/useCombatLayout.js.map +1 -1
  66. package/lib/components/screens/combat/hooks/useCombatState.js.map +1 -1
  67. package/lib/components/screens/controls/ControlsScreen3D.js +1 -1
  68. package/lib/components/screens/controls/ControlsScreen3D.js.map +1 -1
  69. package/lib/components/screens/controls/components/ControlBindingsOverlayHtml.js.map +1 -1
  70. package/lib/components/screens/controls/components/ControlCategoryTabsOverlayHtml.js.map +1 -1
  71. package/lib/components/screens/controls/components/GamepadVisualization3D.js.map +1 -1
  72. package/lib/components/screens/controls/components/InteractiveControlDemoOverlayHtml.js.map +1 -1
  73. package/lib/components/screens/controls/components/Key3D.js.map +1 -1
  74. package/lib/components/screens/controls/components/VisualKeyboard3D.js.map +1 -1
  75. package/lib/components/screens/controls/constants/ControlsConstants.js.map +1 -1
  76. package/lib/components/screens/controls/hooks/useControlsState.js.map +1 -1
  77. package/lib/components/screens/endscreen/EndScreen3D.js.map +1 -1
  78. package/lib/components/screens/endscreen/components/DefeatAnimation3D.js.map +1 -1
  79. package/lib/components/screens/endscreen/components/MatchStatisticsDisplayOverlayHtml.js.map +1 -1
  80. package/lib/components/screens/endscreen/components/NavigationButtonsOverlayHtml.js.map +1 -1
  81. package/lib/components/screens/endscreen/components/PerformanceBreakdownOverlayHtml.js.map +1 -1
  82. package/lib/components/screens/endscreen/components/PerformanceRatingOverlayHtml.js.map +1 -1
  83. package/lib/components/screens/endscreen/components/VictoryAnimation3D.js.map +1 -1
  84. package/lib/components/screens/endscreen/components/WinnerDisplayOverlayHtml.js.map +1 -1
  85. package/lib/components/screens/intro/IntroScreen3D.js +1 -1
  86. package/lib/components/screens/intro/IntroScreen3D.js.map +1 -1
  87. package/lib/components/screens/intro/components/AbilityListOverlayHtml.js.map +1 -1
  88. package/lib/components/screens/intro/components/ArchetypeCardGridOverlayHtml.js.map +1 -1
  89. package/lib/components/screens/intro/components/ArchetypeCardOverlayHtml.js.map +1 -1
  90. package/lib/components/screens/intro/components/ArchetypeDisplayOverlayHtml.js.map +1 -1
  91. package/lib/components/screens/intro/components/EnhancedArchetypeDisplayOverlayHtml.js.map +1 -1
  92. package/lib/components/screens/intro/components/MenuButtonsOverlayHtml.js.map +1 -1
  93. package/lib/components/screens/intro/components/MenuSectionOverlayHtml.js.map +1 -1
  94. package/lib/components/screens/intro/components/StatBarOverlayHtml.js.map +1 -1
  95. package/lib/components/screens/philosophy/PhilosophyScreen3D.js +1 -1
  96. package/lib/components/screens/philosophy/PhilosophyScreen3D.js.map +1 -1
  97. package/lib/components/screens/training/TrainingScreen3D.d.ts.map +1 -1
  98. package/lib/components/screens/training/TrainingScreen3D.js +3 -11
  99. package/lib/components/screens/training/TrainingScreen3D.js.map +1 -1
  100. package/lib/components/screens/training/components/AnatomyControlsOverlayHtml.js.map +1 -1
  101. package/lib/components/screens/training/components/AnatomyOverlay3D.js.map +1 -1
  102. package/lib/components/screens/training/components/FootPlacementMarkers3D.js.map +1 -1
  103. package/lib/components/screens/training/components/FootworkDrillsOverlayHtml.js.map +1 -1
  104. package/lib/components/screens/training/components/HitFeedbackEffect3D.js.map +1 -1
  105. package/lib/components/screens/training/components/TrainingButtonsOverlayHtml.js.map +1 -1
  106. package/lib/components/screens/training/components/TrainingControlsOverlayHtml.js.map +1 -1
  107. package/lib/components/screens/training/components/TrainingDummy3D.js.map +1 -1
  108. package/lib/components/screens/training/components/TrainingFeedbackOverlayHtml.js.map +1 -1
  109. package/lib/components/screens/training/components/TrainingModeSelectorOverlayHtml.js.map +1 -1
  110. package/lib/components/screens/training/components/TrainingStatsOverlayHtml.js.map +1 -1
  111. package/lib/components/screens/training/components/VitalPointMarker3D.js.map +1 -1
  112. package/lib/components/screens/training/components/VitalPointTrainingOverlayHtml.js.map +1 -1
  113. package/lib/components/screens/training/components/hud/TrainingBottomHUD.d.ts.map +1 -1
  114. package/lib/components/screens/training/components/hud/TrainingBottomHUD.js +2 -2
  115. package/lib/components/screens/training/components/hud/TrainingBottomHUD.js.map +1 -1
  116. package/lib/components/screens/training/components/hud/TrainingLeftHUD.js.map +1 -1
  117. package/lib/components/screens/training/components/hud/TrainingRightHUD.js.map +1 -1
  118. package/lib/components/screens/training/components/hud/TrainingTopHUD.js.map +1 -1
  119. package/lib/components/screens/training/hooks/useAttackMovement.js.map +1 -1
  120. package/lib/components/screens/training/hooks/useTrainingActions.d.ts +1 -0
  121. package/lib/components/screens/training/hooks/useTrainingActions.d.ts.map +1 -1
  122. package/lib/components/screens/training/hooks/useTrainingActions.js +6 -4
  123. package/lib/components/screens/training/hooks/useTrainingActions.js.map +1 -1
  124. package/lib/components/screens/training/hooks/useTrainingLayout.d.ts.map +1 -1
  125. package/lib/components/screens/training/hooks/useTrainingLayout.js +11 -5
  126. package/lib/components/screens/training/hooks/useTrainingLayout.js.map +1 -1
  127. package/lib/components/screens/training/hooks/useTrainingState.js.map +1 -1
  128. package/lib/components/shared/base/BaseButton.js.map +1 -1
  129. package/lib/components/shared/base/BaseButtonOverlayHtml.js.map +1 -1
  130. package/lib/components/shared/base/BasePanel.js.map +1 -1
  131. package/lib/components/shared/base/BaseText.js.map +1 -1
  132. package/lib/components/shared/base/useKoreanTheme.js.map +1 -1
  133. package/lib/components/shared/debug/PerformanceDebugOverlayHtml.js.map +1 -1
  134. package/lib/components/shared/mobile/ActionButtons.js.map +1 -1
  135. package/lib/components/shared/mobile/GestureRecognizerPure.js.map +1 -1
  136. package/lib/components/shared/mobile/HapticController.js.map +1 -1
  137. package/lib/components/shared/mobile/MobileControlsPure.js.map +1 -1
  138. package/lib/components/shared/mobile/StanceWheelPure.js.map +1 -1
  139. package/lib/components/shared/mobile/TouchOptimizer.js.map +1 -1
  140. package/lib/components/shared/mobile/VirtualDPad.js.map +1 -1
  141. package/lib/components/shared/three/anatomy/BodySurface.js.map +1 -1
  142. package/lib/components/shared/three/anatomy/BoneAttachedMuscles.js.map +1 -1
  143. package/lib/components/shared/three/anatomy/BoneClothing.js.map +1 -1
  144. package/lib/components/shared/three/anatomy/BoneRenderer.js.map +1 -1
  145. package/lib/components/shared/three/anatomy/Face3D.js.map +1 -1
  146. package/lib/components/shared/three/anatomy/Foot3D.js.map +1 -1
  147. package/lib/components/shared/three/anatomy/Hand3D.js.map +1 -1
  148. package/lib/components/shared/three/effects/ActionFeedback.js.map +1 -1
  149. package/lib/components/shared/three/effects/DamageNumbers.js.map +1 -1
  150. package/lib/components/shared/three/effects/HitEffects3D.js.map +1 -1
  151. package/lib/components/shared/three/effects/PlayerStateIndicators.js.map +1 -1
  152. package/lib/components/shared/three/effects/StanceSymbol3D.js.map +1 -1
  153. package/lib/components/shared/three/effects/StanceTransitionEffect.js.map +1 -1
  154. package/lib/components/shared/three/effects/VitalPointMarkers3D.js.map +1 -1
  155. package/lib/components/shared/three/indicators/ElementalColorSystem.js.map +1 -1
  156. package/lib/components/shared/three/indicators/GuardIndicator.js.map +1 -1
  157. package/lib/components/shared/three/indicators/HapticFeedback.js.map +1 -1
  158. package/lib/components/shared/three/indicators/StanceChangeIndicator.js.map +1 -1
  159. package/lib/components/shared/three/models/Player3DWithTransitions.js.map +1 -1
  160. package/lib/components/shared/three/models/SkeletalPlayer3D.d.ts.map +1 -1
  161. package/lib/components/shared/three/models/SkeletalPlayer3D.js +7 -5
  162. package/lib/components/shared/three/models/SkeletalPlayer3D.js.map +1 -1
  163. package/lib/components/shared/three/optimization/AdaptiveQuality.js.map +1 -1
  164. package/lib/components/shared/three/scene/AtmosphericParticles3D.js.map +1 -1
  165. package/lib/components/shared/three/scene/BackgroundScene3D.js.map +1 -1
  166. package/lib/components/shared/three/scene/CombatArena3D.js.map +1 -1
  167. package/lib/components/shared/three/scene/KoreanSignage3D.js.map +1 -1
  168. package/lib/components/shared/three/ui/ArchetypeCard.js.map +1 -1
  169. package/lib/components/shared/three/ui/BodyPartHealthDisplay.js.map +1 -1
  170. package/lib/components/shared/three/ui/BreathingIndicator2.js.map +1 -1
  171. package/lib/components/shared/three/ui/CombatReadinessBar.js.map +1 -1
  172. package/lib/components/shared/three/ui/ComboCounter.js.map +1 -1
  173. package/lib/components/shared/three/ui/HealthBar.js.map +1 -1
  174. package/lib/components/shared/three/ui/KoreanButton.js.map +1 -1
  175. package/lib/components/shared/three/ui/KoreanPanel.js.map +1 -1
  176. package/lib/components/shared/three/ui/KoreanText.js.map +1 -1
  177. package/lib/components/shared/three/ui/MenuList.js.map +1 -1
  178. package/lib/components/shared/three/ui/PlayerHUD.js.map +1 -1
  179. package/lib/components/shared/three/ui/ProgressBar.js.map +1 -1
  180. package/lib/components/shared/three/ui/SpeedIndicatorHUD.js.map +1 -1
  181. package/lib/components/shared/three/ui/StaminaBar.js.map +1 -1
  182. package/lib/components/shared/three/ui/TechniqueBar.js.map +1 -1
  183. package/lib/components/shared/three/ui/TechniqueCard.js.map +1 -1
  184. package/lib/components/shared/three/ui/VitalPointOverlayControlsHtml.js.map +1 -1
  185. package/lib/components/shared/ui/BackButton.js.map +1 -1
  186. package/lib/components/shared/ui/BaseHUDContainer.js.map +1 -1
  187. package/lib/components/shared/ui/CombatTimer.js.map +1 -1
  188. package/lib/components/shared/ui/ErrorModal.js.map +1 -1
  189. package/lib/components/shared/ui/LoadingState.js.map +1 -1
  190. package/lib/components/shared/ui/SplashScreen.js +2 -2
  191. package/lib/components/shared/ui/SplashScreen.js.map +1 -1
  192. package/lib/components/shared/ui/VitalPointOverlayControlsPure.js.map +1 -1
  193. package/lib/components/shared/ui/VolumeControl.js.map +1 -1
  194. package/lib/components/shared/ui/shared/ConfirmDialog.js.map +1 -1
  195. package/lib/components/ui/combat/BalanceIndicatorOverlayHtml.js.map +1 -1
  196. package/lib/constants/bodyDimensions.js.map +1 -1
  197. package/lib/constants/bodyRenderingConstants.js.map +1 -1
  198. package/lib/data/archetypeClothing.js.map +1 -1
  199. package/lib/data/archetypePhysicalAttributes.js.map +1 -1
  200. package/lib/data/techniqueMappings.js.map +1 -1
  201. package/lib/data/techniques.js.map +1 -1
  202. package/lib/hooks/useActionFeedback.js.map +1 -1
  203. package/lib/hooks/useBalanceAnimations.js.map +1 -1
  204. package/lib/hooks/useCombatTimer.js.map +1 -1
  205. package/lib/hooks/useDebounce.js.map +1 -1
  206. package/lib/hooks/useHUDLayout.d.ts.map +1 -1
  207. package/lib/hooks/useHUDLayout.js +3 -2
  208. package/lib/hooks/useHUDLayout.js.map +1 -1
  209. package/lib/hooks/useHandPoseTransitions.js.map +1 -1
  210. package/lib/hooks/useKeyboardControls.js.map +1 -1
  211. package/lib/hooks/useMatchCountdown.js.map +1 -1
  212. package/lib/hooks/useMuscleActivation.js.map +1 -1
  213. package/lib/hooks/usePauseMenu.js.map +1 -1
  214. package/lib/hooks/usePlayerAnimation.js.map +1 -1
  215. package/lib/hooks/useResponsiveLayout.js.map +1 -1
  216. package/lib/hooks/useRoundTransition.js.map +1 -1
  217. package/lib/hooks/useSkeletalAnimation.d.ts.map +1 -1
  218. package/lib/hooks/useSkeletalAnimation.js +1 -1
  219. package/lib/hooks/useSkeletalAnimation.js.map +1 -1
  220. package/lib/hooks/useTechniqueSelection.js.map +1 -1
  221. package/lib/hooks/useThrottle.js.map +1 -1
  222. package/lib/hooks/useTouchControls.js.map +1 -1
  223. package/lib/hooks/useWebGLContextLossHandler.js.map +1 -1
  224. package/lib/hooks/useWindowSize.js.map +1 -1
  225. package/lib/systems/CombatSystem.js.map +1 -1
  226. package/lib/systems/EffectCalculator.js.map +1 -1
  227. package/lib/systems/LayoutSystem.js.map +1 -1
  228. package/lib/systems/PlayerEffectManager.js.map +1 -1
  229. package/lib/systems/ResponsiveScaling.js.map +1 -1
  230. package/lib/systems/TrigramSystem.js.map +1 -1
  231. package/lib/systems/VitalPointSystem.js.map +1 -1
  232. package/lib/systems/ai/AIPersonality.js.map +1 -1
  233. package/lib/systems/ai/AdaptiveDifficulty.js +16 -16
  234. package/lib/systems/ai/AdaptiveDifficulty.js.map +1 -1
  235. package/lib/systems/ai/ArchetypeEnforcer.js.map +1 -1
  236. package/lib/systems/ai/ComboSystem.js.map +1 -1
  237. package/lib/systems/ai/DecisionTree.js.map +1 -1
  238. package/lib/systems/ai/TrainingAI.js.map +1 -1
  239. package/lib/systems/ai/types.js.map +1 -1
  240. package/lib/systems/animation/builders/AnimationBuilder.js.map +1 -1
  241. package/lib/systems/animation/builders/HandPoseApplicator.js.map +1 -1
  242. package/lib/systems/animation/builders/HandPoses.js.map +1 -1
  243. package/lib/systems/animation/builders/KeyframeConfig.js.map +1 -1
  244. package/lib/systems/animation/builders/KeyframeInterpolation.js.map +1 -1
  245. package/lib/systems/animation/builders/KickPhaseApplicator.d.ts +6 -0
  246. package/lib/systems/animation/builders/KickPhaseApplicator.d.ts.map +1 -1
  247. package/lib/systems/animation/builders/KickPhaseApplicator.js +16 -9
  248. package/lib/systems/animation/builders/KickPhaseApplicator.js.map +1 -1
  249. package/lib/systems/animation/builders/KoreanGuardPositions.d.ts +4 -4
  250. package/lib/systems/animation/builders/KoreanGuardPositions.js.map +1 -1
  251. package/lib/systems/animation/builders/MartialArtsAnimationBuilder.d.ts +1 -1
  252. package/lib/systems/animation/builders/MartialArtsAnimationBuilder.d.ts.map +1 -1
  253. package/lib/systems/animation/builders/MartialArtsAnimationBuilder.js +5 -5
  254. package/lib/systems/animation/builders/MartialArtsAnimationBuilder.js.map +1 -1
  255. package/lib/systems/animation/builders/MartialArtsConstants.d.ts +112 -71
  256. package/lib/systems/animation/builders/MartialArtsConstants.d.ts.map +1 -1
  257. package/lib/systems/animation/builders/MartialArtsConstants.js +113 -72
  258. package/lib/systems/animation/builders/MartialArtsConstants.js.map +1 -1
  259. package/lib/systems/animation/builders/MartialPoseApplicator.js.map +1 -1
  260. package/lib/systems/animation/builders/PunchPhaseApplicator.js.map +1 -1
  261. package/lib/systems/animation/builders/SkeletonRig.js.map +1 -1
  262. package/lib/systems/animation/builders/TrigramGuardApplicator.js.map +1 -1
  263. package/lib/systems/animation/catalogs/AttackAnimations.js.map +1 -1
  264. package/lib/systems/animation/catalogs/BasicAnimations.js.map +1 -1
  265. package/lib/systems/animation/catalogs/ComboAnimations.js.map +1 -1
  266. package/lib/systems/animation/catalogs/DarkOpsAnimations.js.map +1 -1
  267. package/lib/systems/animation/catalogs/DefensiveAnimations.js.map +1 -1
  268. package/lib/systems/animation/catalogs/ElbowKneeAnimations.js.map +1 -1
  269. package/lib/systems/animation/catalogs/EnhancedAttackAnimations.js.map +1 -1
  270. package/lib/systems/animation/catalogs/EnhancedElbowKneeAnimations.js.map +1 -1
  271. package/lib/systems/animation/catalogs/FootworkSkeletalAnimations.js.map +1 -1
  272. package/lib/systems/animation/catalogs/GamRedirectionAnimations.js.map +1 -1
  273. package/lib/systems/animation/catalogs/GamStanceAnimations.js +21 -0
  274. package/lib/systems/animation/catalogs/GamStanceAnimations.js.map +1 -0
  275. package/lib/systems/animation/catalogs/GamTechniqueAnimations.js +34 -2
  276. package/lib/systems/animation/catalogs/GamTechniqueAnimations.js.map +1 -1
  277. package/lib/systems/animation/catalogs/GanStanceAnimations.js.map +1 -1
  278. package/lib/systems/animation/catalogs/GanTechniqueAnimations.js.map +1 -1
  279. package/lib/systems/animation/catalogs/GeonStanceAnimations.js.map +1 -1
  280. package/lib/systems/animation/catalogs/GonTechniqueAnimations.d.ts +9 -0
  281. package/lib/systems/animation/catalogs/GonTechniqueAnimations.d.ts.map +1 -1
  282. package/lib/systems/animation/catalogs/GonTechniqueAnimations.js +288 -0
  283. package/lib/systems/animation/catalogs/GonTechniqueAnimations.js.map +1 -0
  284. package/lib/systems/animation/catalogs/GrapplingAnimations.js.map +1 -1
  285. package/lib/systems/animation/catalogs/JinStanceAnimations.js.map +1 -1
  286. package/lib/systems/animation/catalogs/JinTechniqueAnimations.js.map +1 -1
  287. package/lib/systems/animation/catalogs/KickAnimations.d.ts +2 -2
  288. package/lib/systems/animation/catalogs/KickAnimations.js +2 -2
  289. package/lib/systems/animation/catalogs/KickAnimations.js.map +1 -1
  290. package/lib/systems/animation/catalogs/LiStanceAnimations.js +14 -1
  291. package/lib/systems/animation/catalogs/LiStanceAnimations.js.map +1 -1
  292. package/lib/systems/animation/catalogs/LiTechniqueAnimations.js.map +1 -1
  293. package/lib/systems/animation/catalogs/MovementAnimations.js.map +1 -1
  294. package/lib/systems/animation/catalogs/PunchAnimations.d.ts +1 -1
  295. package/lib/systems/animation/catalogs/PunchAnimations.js +1 -1
  296. package/lib/systems/animation/catalogs/PunchAnimations.js.map +1 -1
  297. package/lib/systems/animation/catalogs/RecoveryAnimations.js.map +1 -1
  298. package/lib/systems/animation/catalogs/SonStanceAnimations.js.map +1 -1
  299. package/lib/systems/animation/catalogs/SonTechniqueAnimations.js.map +1 -1
  300. package/lib/systems/animation/catalogs/SpecializedPunchAnimations.js.map +1 -1
  301. package/lib/systems/animation/catalogs/StanceAnimations.js.map +1 -1
  302. package/lib/systems/animation/catalogs/StanceAttackAnimations.js.map +1 -1
  303. package/lib/systems/animation/catalogs/StanceGuardPoses.d.ts +6 -6
  304. package/lib/systems/animation/catalogs/StanceGuardPoses.js +36 -36
  305. package/lib/systems/animation/catalogs/StanceGuardPoses.js.map +1 -1
  306. package/lib/systems/animation/catalogs/StanceIdleAnimations.js.map +1 -1
  307. package/lib/systems/animation/catalogs/StanceLocomotionAnimations.js.map +1 -1
  308. package/lib/systems/animation/catalogs/StepSkeletalAnimations.js.map +1 -1
  309. package/lib/systems/animation/catalogs/TaeJointLockAnimations.js.map +1 -1
  310. package/lib/systems/animation/catalogs/TaeStanceAnimations.js.map +1 -1
  311. package/lib/systems/animation/constants/AnatomicalLimits.js.map +1 -1
  312. package/lib/systems/animation/core/AnimationHitTiming.js.map +1 -1
  313. package/lib/systems/animation/core/AnimationOptimizations.js.map +1 -1
  314. package/lib/systems/animation/core/AnimationPriority.js +15 -15
  315. package/lib/systems/animation/core/AnimationPriority.js.map +1 -1
  316. package/lib/systems/animation/core/AnimationRegistry.d.ts +30 -0
  317. package/lib/systems/animation/core/AnimationRegistry.d.ts.map +1 -1
  318. package/lib/systems/animation/core/AnimationRegistry.js +74 -12
  319. package/lib/systems/animation/core/AnimationRegistry.js.map +1 -1
  320. package/lib/systems/animation/core/AnimationStateMachine.js +16 -16
  321. package/lib/systems/animation/core/AnimationStateMachine.js.map +1 -1
  322. package/lib/systems/animation/core/AnimationTransitions.d.ts.map +1 -1
  323. package/lib/systems/animation/core/AnimationTransitions.js +34 -0
  324. package/lib/systems/animation/core/AnimationTransitions.js.map +1 -1
  325. package/lib/systems/animation/core/LateralityTransform.js.map +1 -1
  326. package/lib/systems/animation/core/RecoveryPhaseEnhancer.js.map +1 -1
  327. package/lib/systems/animation/core/TechniqueAnimationMapper.js.map +1 -1
  328. package/lib/systems/animation/core/TechniqueAnimationMapping.js.map +1 -1
  329. package/lib/systems/animation/core/index.d.ts +1 -1
  330. package/lib/systems/animation/core/index.d.ts.map +1 -1
  331. package/lib/systems/animation/core/types.d.ts +24 -0
  332. package/lib/systems/animation/core/types.d.ts.map +1 -1
  333. package/lib/systems/animation/core/types.js +27 -11
  334. package/lib/systems/animation/core/types.js.map +1 -1
  335. package/lib/systems/animation/systems/AdvancedJointMovements.js.map +1 -1
  336. package/lib/systems/animation/systems/BodyFacingSystem.js.map +1 -1
  337. package/lib/systems/animation/systems/FacialExpressions.js.map +1 -1
  338. package/lib/systems/animation/systems/FallAnimations.js.map +1 -1
  339. package/lib/systems/animation/systems/MuscleActivation.js.map +1 -1
  340. package/lib/systems/bodypart/BodyPartDamageIntegration.js.map +1 -1
  341. package/lib/systems/bodypart/BodyPartHealthSystem.js.map +1 -1
  342. package/lib/systems/bodypart/BodyPartPositionMapping.js.map +1 -1
  343. package/lib/systems/bodypart/CombatInjuryIntegration.js.map +1 -1
  344. package/lib/systems/bodypart/InjuryIntegration.js.map +1 -1
  345. package/lib/systems/bodypart/InjuryTracker.js.map +1 -1
  346. package/lib/systems/bodypart/MovementPenaltySystem.js.map +1 -1
  347. package/lib/systems/bodypart/PlayerInjuryTrackingManager.js.map +1 -1
  348. package/lib/systems/bodypart/types.js.map +1 -1
  349. package/lib/systems/breathing/BreathingDisruptionSystem.js +19 -19
  350. package/lib/systems/breathing/BreathingDisruptionSystem.js.map +1 -1
  351. package/lib/systems/breathing/feedback.js.map +1 -1
  352. package/lib/systems/breathing/integration.js.map +1 -1
  353. package/lib/systems/combat/BalanceSystem.js +19 -19
  354. package/lib/systems/combat/BalanceSystem.js.map +1 -1
  355. package/lib/systems/combat/BreakingStatusEffects.js.map +1 -1
  356. package/lib/systems/combat/CombatStateSystem.js +17 -17
  357. package/lib/systems/combat/CombatStateSystem.js.map +1 -1
  358. package/lib/systems/combat/ConsciousnessSystem.js +24 -24
  359. package/lib/systems/combat/ConsciousnessSystem.js.map +1 -1
  360. package/lib/systems/combat/FallIntegration.js.map +1 -1
  361. package/lib/systems/combat/GrappleSystem.js.map +1 -1
  362. package/lib/systems/combat/LimbExposureSystem.js.map +1 -1
  363. package/lib/systems/combat/PainResponseSystem.js +21 -21
  364. package/lib/systems/combat/PainResponseSystem.js.map +1 -1
  365. package/lib/systems/combat/TrainingCombatSystem.js.map +1 -1
  366. package/lib/systems/combat/painConsciousnessUtils.js.map +1 -1
  367. package/lib/systems/combat/typeGuards.js.map +1 -1
  368. package/lib/systems/effects.js.map +1 -1
  369. package/lib/systems/game.js.map +1 -1
  370. package/lib/systems/movement/InjuryMovementModifier.js.map +1 -1
  371. package/lib/systems/movement/helpers/AccelerationUpdater.js.map +1 -1
  372. package/lib/systems/movement/helpers/accelerationUtils.js.map +1 -1
  373. package/lib/systems/movement/integration.js.map +1 -1
  374. package/lib/systems/physics/AttackMovementPhysics.js.map +1 -1
  375. package/lib/systems/physics/CollisionDetection.js.map +1 -1
  376. package/lib/systems/physics/CoordinateMapper.js.map +1 -1
  377. package/lib/systems/physics/KnockbackPhysics.js.map +1 -1
  378. package/lib/systems/physics/MovementPhysics.js.map +1 -1
  379. package/lib/systems/physics/PhysicalReachCalculator.js.map +1 -1
  380. package/lib/systems/physics/SpeedModifierSystem.js +6 -6
  381. package/lib/systems/physics/SpeedModifierSystem.js.map +1 -1
  382. package/lib/systems/trigram/KoreanCulture.js.map +1 -1
  383. package/lib/systems/trigram/KoreanTechniques.js.map +1 -1
  384. package/lib/systems/trigram/StanceManager.js.map +1 -1
  385. package/lib/systems/trigram/TransitionCalculator.js.map +1 -1
  386. package/lib/systems/trigram/TrigramCalculator.js.map +1 -1
  387. package/lib/systems/trigram/techniques/DarkOpsTechniques.js.map +1 -1
  388. package/lib/systems/trigram/techniques/GamTechniques.js.map +1 -1
  389. package/lib/systems/trigram/techniques/GanTechniques.js.map +1 -1
  390. package/lib/systems/trigram/techniques/GeonTechniques.js.map +1 -1
  391. package/lib/systems/trigram/techniques/GonTechniques.js.map +1 -1
  392. package/lib/systems/trigram/techniques/JinTechniques.js.map +1 -1
  393. package/lib/systems/trigram/techniques/LiTechniques.js.map +1 -1
  394. package/lib/systems/trigram/techniques/SonTechniques.js.map +1 -1
  395. package/lib/systems/trigram/techniques/TaeTechniques.js.map +1 -1
  396. package/lib/systems/trigram/techniques/TechniqueConfig.js.map +1 -1
  397. package/lib/systems/trigram/techniques/index.js.map +1 -1
  398. package/lib/systems/trigram/types/GonTechniqueExtensions.js.map +1 -1
  399. package/lib/systems/trigram/types.js.map +1 -1
  400. package/lib/systems/types.js.map +1 -1
  401. package/lib/systems/vitalpoint/DamageCalculator.js.map +1 -1
  402. package/lib/systems/vitalpoint/HitDetection.js.map +1 -1
  403. package/lib/systems/vitalpoint/KoreanAnatomy.js.map +1 -1
  404. package/lib/systems/vitalpoint/KoreanVitalPoints.js.map +1 -1
  405. package/lib/systems/vitalpoint/MeridianVitalPointMapping.js.map +1 -1
  406. package/lib/systems/vitalpoint/VitalPointsData.js.map +1 -1
  407. package/lib/types/AccessibilityTypes.js.map +1 -1
  408. package/lib/types/LayoutTypes.js.map +1 -1
  409. package/lib/types/PhysicsTypes.js.map +1 -1
  410. package/lib/types/common.js.map +1 -1
  411. package/lib/types/constants/animations.js.map +1 -1
  412. package/lib/types/constants/colors.js.map +1 -1
  413. package/lib/types/constants/designSystem.js.map +1 -1
  414. package/lib/types/constants/index.js.map +1 -1
  415. package/lib/types/constants/layout.d.ts +21 -0
  416. package/lib/types/constants/layout.d.ts.map +1 -1
  417. package/lib/types/constants/layout.js +22 -1
  418. package/lib/types/constants/layout.js.map +1 -1
  419. package/lib/types/constants/performance.js.map +1 -1
  420. package/lib/types/constants/typography.js.map +1 -1
  421. package/lib/types/constants/ui.js.map +1 -1
  422. package/lib/types/facial.js +19 -19
  423. package/lib/types/facial.js.map +1 -1
  424. package/lib/types/hand-animation.js.map +1 -1
  425. package/lib/types/injury.js.map +1 -1
  426. package/lib/types/muscle.js.map +1 -1
  427. package/lib/types/physics.js.map +1 -1
  428. package/lib/types/physicsConstants.js.map +1 -1
  429. package/lib/types/player-visual.d.ts +1 -1
  430. package/lib/types/player-visual.d.ts.map +1 -1
  431. package/lib/types/skeletal.js.map +1 -1
  432. package/lib/types/techniqueId.js.map +1 -1
  433. package/lib/utils/accessibility.js.map +1 -1
  434. package/lib/utils/arenaWorldDimensions.js.map +1 -1
  435. package/lib/utils/assetConfig.js.map +1 -1
  436. package/lib/utils/characterScaling.js.map +1 -1
  437. package/lib/utils/colorHelpers.js.map +1 -1
  438. package/lib/utils/colorUtils.js.map +1 -1
  439. package/lib/utils/combatReadiness.js.map +1 -1
  440. package/lib/utils/controlMapping.js.map +1 -1
  441. package/lib/utils/deviceDetection.js +6 -7
  442. package/lib/utils/deviceDetection.js.map +1 -1
  443. package/lib/utils/effectUtils.js.map +1 -1
  444. package/lib/utils/fabricTextures.js.map +1 -1
  445. package/lib/utils/hapticFeedback.js.map +1 -1
  446. package/lib/utils/haptics.js.map +1 -1
  447. package/lib/utils/htmlOverlayHelpers.js.map +1 -1
  448. package/lib/utils/inputSystem.js.map +1 -1
  449. package/lib/utils/koreanThemeHelpers.js.map +1 -1
  450. package/lib/utils/math.js.map +1 -1
  451. package/lib/utils/mobileLayoutHelpers.js.map +1 -1
  452. package/lib/utils/mobileUIUtils.js.map +1 -1
  453. package/lib/utils/performance/PerformanceMonitor.js.map +1 -1
  454. package/lib/utils/performance/PerformanceOverlay3D.js.map +1 -1
  455. package/lib/utils/performance/usePerformanceMonitor.js.map +1 -1
  456. package/lib/utils/performanceOptimization.js.map +1 -1
  457. package/lib/utils/player3DHelpers.js.map +1 -1
  458. package/lib/utils/playerUtils.js.map +1 -1
  459. package/lib/utils/responsiveLayout.js.map +1 -1
  460. package/lib/utils/responsiveLayoutHelpers.d.ts +7 -0
  461. package/lib/utils/responsiveLayoutHelpers.d.ts.map +1 -1
  462. package/lib/utils/responsiveLayoutHelpers.js +16 -2
  463. package/lib/utils/responsiveLayoutHelpers.js.map +1 -1
  464. package/lib/utils/responsiveOrientationConstants.js.map +1 -1
  465. package/lib/utils/safeAreaUtils.js.map +1 -1
  466. package/lib/utils/sharedPhysicsConfig.js.map +1 -1
  467. package/lib/utils/skeletonScaling.js.map +1 -1
  468. package/lib/utils/stanceHelpers.js.map +1 -1
  469. package/lib/utils/threeObjectPool.js.map +1 -1
  470. package/lib/utils/visualEffects.js.map +1 -1
  471. package/package.json +7 -7
@@ -1 +1 @@
1
- {"version":3,"file":"CombatScreen3D.js","names":[],"sources":["../../../../src/components/screens/combat/CombatScreen3D.tsx"],"sourcesContent":["/**\n * CombatScreen3D - Three.js-based combat screen (Black Trigram 흑괘)\n *\n * Maintains all existing combat logic and state management\n * Uses Html overlays for UI and 3D meshes for game objects\n */\n\nimport { Canvas } from \"@react-three/fiber\";\nimport { Html } from \"@react-three/drei\";\nimport {\n Bloom,\n EffectComposer,\n Noise,\n Vignette,\n} from \"@react-three/postprocessing\";\nimport React, {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { useAudio } from \"../../../audio/AudioProvider\";\nimport { useActionFeedback } from \"../../../hooks/useActionFeedback\";\nimport { useCombatTimer } from \"../../../hooks/useCombatTimer\";\nimport { useKeyboardControls } from \"../../../hooks/useKeyboardControls\";\nimport { usePlayerAnimation } from \"../../../hooks/usePlayerAnimation\";\nimport { useRoundTransition } from \"../../../hooks/useRoundTransition\";\nimport { useTechniqueSelection } from \"../../../hooks/useTechniqueSelection\";\nimport { useWebGLContextLossHandler } from \"../../../hooks/useWebGLContextLossHandler\";\nimport { useCombatAttackMovement } from \"./hooks/useCombatAttackMovement\";\nimport { HitEffect, PlayerState } from \"../../../systems\";\nimport { CombatSystem } from \"../../../systems/CombatSystem\";\nimport {\n AdaptiveDifficulty,\n getPersonalityByArchetype,\n} from \"../../../systems/ai\";\nimport {\n AnimationEvents,\n AnimationState,\n AnimationType,\n determineRecoveryType,\n getAnimation,\n getRecoveryAnimationState,\n resolveTechniqueAnimation,\n} from \"../../../systems/animation\";\nimport { BalanceSystem } from \"../../../systems/combat/BalanceSystem\";\nimport type { BalancePlayerState } from \"../../../systems/combat/BalanceSystem\";\nimport { HitEffectType } from \"../../../systems/effects\";\nimport { injuryMovementModifier } from \"../../../systems/movement/InjuryMovementModifier\";\nimport { TRIGRAM_STANCES_ORDER } from \"../../../systems/trigram/types\";\nimport { TRIGRAM_TECHNIQUES } from \"../../../systems/trigram/techniques\";\nimport type { KoreanTechnique } from \"../../../systems/vitalpoint/types\";\nimport {\n CombatState,\n GameMode,\n PlayerArchetype,\n Position,\n TrigramStance,\n} from \"../../../types\";\nimport { Injury, InjuryType } from \"../../../types/injury\";\nimport { Z_INDEX } from \"../../../types/LayoutTypes\";\nimport { getMobileControlsBottom } from \"../../../types/constants/layout\";\nimport {\n FONT_FAMILY,\n getPerformanceSettings,\n KOREAN_COLORS,\n ROUND_ANNOUNCEMENT_TIMINGS,\n} from \"@/types/constants\";\nimport { getAnimationTypeForTechnique } from \"../../../data/techniqueMappings\";\nimport { toHexColor } from \"../../../utils/colorHelpers\";\nimport { usePlayerMovement } from \"../../../utils/inputSystem\";\nimport { PerformanceOverlay3D } from \"../../../utils/performance\";\nimport { createPlayerFromArchetype } from \"../../../utils/playerUtils\";\nimport { createCameraConfig } from \"../../../utils/sharedPhysicsConfig\";\nimport { useAdaptiveQuality } from \"../../shared/three/optimization\";\nimport { useKoreanTheme } from \"../../shared/base/useKoreanTheme\";\nimport {\n ActionFeedback,\n TechniqueName,\n} from \"../../shared/three/effects/ActionFeedback\";\nimport { DamageNumbers } from \"../../shared/three/effects/DamageNumbers\";\nimport HitEffects3D from \"../../shared/three/effects/HitEffects3D\";\nimport { VitalPointMarkers3D } from \"../../shared/three/effects/VitalPointMarkers3D\";\nimport { StanceChangeIndicator } from \"../../shared/three/indicators/StanceChangeIndicator\";\nimport { CombatArena3D } from \"../../shared/three/scene/CombatArena3D\";\nimport { BreathingIndicator } from \"../../shared/three/ui/BreathingIndicator\";\nimport { ComboCounter } from \"../../shared/three/ui/ComboCounter\";\nimport { VitalPointOverlayControlsHtml } from \"../../shared/three/ui/VitalPointOverlayControlsHtml\";\nimport { KeyboardHints } from \"./components/controls/KeyboardHints\";\nimport { MatchCountdown } from \"./components/feedback/MatchCountdown\";\nimport { RoundAnnouncement } from \"./components/feedback/RoundAnnouncementOverlayHtml\";\nimport { RoundDisplayStatus } from \"./components/feedback/RoundDisplayStatus\";\nimport { RoundStartAnnouncement } from \"./components/feedback/RoundStartAnnouncementOverlayHtml\";\nimport { InputBufferDisplay } from \"./components/indicators/InputBufferDisplay\";\nimport { GestureEvent } from \"../../../hooks/useTouchControls\";\nimport {\n MovementType,\n SpeedModifierSystem,\n} from \"../../../systems/physics/SpeedModifierSystem\";\nimport { Technique } from \"../../../types\";\nimport {\n animationStateToPlayerAnimation,\n convertPlayerStateToProps,\n getBalanceState,\n} from \"../../../utils/player3DHelpers\";\nimport {\n GestureRecognizerPure,\n MobileControlsOverlay,\n StanceWheelPure,\n} from \"../../shared/mobile\";\nimport { ButtonEventType } from \"../../shared/mobile/ActionButtons\";\nimport { Direction, DPadEventType } from \"../../shared/mobile/VirtualDPad\";\nimport { Player3DWithTransitions } from \"../../shared/three/models/Player3DWithTransitions\";\nimport { PauseMenu } from \"./components/controls/PauseMenu\";\nimport { TraumaOverlay3D } from \"./components/effects/TraumaOverlay3D\";\nimport { CombatParticleEffects3D } from \"./components/effects/CombatParticleEffects3D\";\nimport {\n CombatBottomHUD,\n CombatLeftHUD,\n CombatPortraitStatusStrip,\n CombatRightHUD,\n CombatTopHUD,\n} from \"./components/hud\";\nimport { FPSMonitor } from \"./components/hud/FPSMonitor\";\nimport { PlayerStateOverlayHtml } from \"./components/hud/PlayerStateOverlayHtml\";\nimport { BalanceIndicatorOverlayHtml } from \"../../ui/combat/BalanceIndicatorOverlayHtml\";\nimport {\n ANNOUNCEMENT_FADE_OUT_DELAY,\n calculateAccuracy,\n STANCE_INDEX_MAP,\n} from \"./helpers\";\nimport { AnimationUpdater } from \"./helpers/AnimationUpdater\";\nimport { AccelerationUpdater } from \"../../../systems/movement/helpers/AccelerationUpdater\";\nimport { isRunningSpeed } from \"../../../systems/movement/helpers/accelerationUtils\";\nimport { useAICombat } from \"./hooks/useAICombat\";\nimport { useCombatActions } from \"./hooks/useCombatActions\";\nimport { useCombatAudio } from \"./hooks/useCombatAudio\";\nimport { useCombatLayout } from \"./hooks/useCombatLayout\";\nimport { useCombatState } from \"./hooks/useCombatState\";\n\n/**\n * Props for the CombatScreen3D component.\n * Provides all state and callbacks required for the 3D combat screen.\n */\nexport interface CombatScreen3DProps {\n /**\n * Array of player states (expects exactly 2 players).\n * Each PlayerState contains all combat and status information for a player.\n */\n readonly players: readonly PlayerState[];\n /**\n * Callback to update a player's state by index.\n * @param playerIndex - Index of the player to update (0 or 1).\n * @param updates - Partial PlayerState with updated fields.\n */\n readonly onPlayerUpdate: (\n playerIndex: number,\n updates: Partial<PlayerState>,\n ) => void;\n /**\n * Current round number (1-based).\n */\n readonly currentRound: number;\n /**\n * Remaining time in seconds for the current round.\n */\n readonly timeRemaining: number;\n /**\n * Whether combat is currently paused.\n */\n readonly isPaused: boolean;\n /**\n * Callback when the user exits to the menu.\n */\n readonly onReturnToMenu: () => void;\n /**\n * Callback when the match ends, with the winner's index (0 or 1).\n * @param winner - Index of the winning player.\n */\n readonly onGameEnd: (winner: number) => void;\n /**\n * Optional game mode (affects rules/behavior).\n */\n readonly gameMode?: GameMode;\n /**\n * Canvas width in pixels. Defaults to 1200.\n */\n readonly width?: number;\n /**\n * Canvas height in pixels. Defaults to 800.\n */\n readonly height?: number;\n /**\n * Enable adaptive quality adjustment (default: true on mobile)\n */\n readonly enableAdaptiveQuality?: boolean;\n /**\n * Show performance overlay in dev mode (default: import.meta.env.DEV)\n */\n readonly showPerformanceOverlay?: boolean;\n}\n\n/**\n * CombatScreen3D Component\n * Three.js-based combat screen with 3D characters and effects\n */\n\n/**\n * AdaptiveQualityWrapper - Internal component to use adaptive quality hook\n * Must be inside Canvas to use useFrame from @react-three/fiber\n *\n * Hoisted outside CombatScreen3D to avoid \"Cannot create components during render\"\n * warnings from react-hooks/component-creation. Keeps the component type stable\n * across renders of the parent.\n */\nconst AdaptiveQualityWrapper: React.FC<{\n readonly enabled: boolean;\n readonly isMobile: boolean;\n readonly children: React.ReactNode;\n}> = ({ enabled, isMobile, children }) => {\n useAdaptiveQuality(enabled, isMobile, (newQuality) => {\n if (import.meta.env.DEV) {\n console.log(`[CombatScreen3D] Quality adjusted to: ${newQuality}`);\n }\n });\n\n return <>{children}</>;\n};\n\nexport const CombatScreen3D: React.FC<CombatScreen3DProps> = ({\n players,\n onPlayerUpdate,\n currentRound,\n timeRemaining,\n isPaused,\n onReturnToMenu,\n onGameEnd,\n width = 1200,\n height = 800,\n enableAdaptiveQuality,\n showPerformanceOverlay = import.meta.env.DEV,\n}) => {\n const [contentReady, setContentReady] = useState(false);\n\n const contextLossCountRef = useRef(0);\n\n useWebGLContextLossHandler({\n onContextLost: () => {\n console.warn(\"⚠️ WebGL context lost in CombatScreen\");\n contextLossCountRef.current += 1;\n setContentReady(false);\n },\n onContextRestored: () => {\n setTimeout(() => setContentReady(true), 100);\n },\n autoRestore: true,\n });\n\n useEffect(() => {\n const timer = setTimeout(() => setContentReady(true), 50);\n return () => clearTimeout(timer);\n }, []);\n\n const audio = useAudio();\n\n useEffect(() => {\n if (import.meta.env.DEV) {\n performance.mark(\"combat-3d-render-start\");\n return () => {\n performance.mark(\"combat-3d-render-end\");\n performance.measure(\n \"combat-3d-render\",\n \"combat-3d-render-start\",\n \"combat-3d-render-end\",\n );\n };\n }\n }, []);\n\n const { arenaBounds, isMobile, isPortrait, screenSize, layoutConstants } =\n useCombatLayout(width, height);\n\n const theme = useKoreanTheme({\n variant: \"primary\",\n size: \"md\",\n isMobile,\n });\n\n const positionScale = useMemo(() => {\n if (isMobile) {\n return 1.0;\n }\n\n switch (screenSize) {\n case \"mobile\":\n return 1.0; // Mobile already has special handling\n case \"tablet\":\n return 1.0;\n case \"desktop\":\n return 1.0;\n case \"large\":\n return 1.25;\n case \"xlarge\":\n return 1.5; // 4K displays need 1.5x offsets\n default:\n return 1.0;\n }\n }, [isMobile, screenSize]);\n\n const cameraConfig = useMemo(() => {\n const base = createCameraConfig(isMobile);\n if (!isPortrait) return base;\n return {\n ...base,\n fov: Math.min(80, base.fov + 15),\n position: [base.position[0], base.position[1], base.position[2] + 4] as [\n number,\n number,\n number,\n ],\n };\n }, [isMobile, isPortrait]);\n\n const renderConfig = useMemo(() => {\n const performanceSettings = getPerformanceSettings(width, isMobile);\n\n return {\n shadowMapSize: performanceSettings.shadowMapSize,\n dpr: performanceSettings.dpr,\n antialias: performanceSettings.antialias,\n maxParticles: performanceSettings.maxParticles,\n postProcessing: performanceSettings.postProcessing,\n };\n }, [isMobile, width]);\n\n const shouldEnableAdaptiveQuality = enableAdaptiveQuality ?? isMobile;\n\n const { state: combatState, actions: combatActions } = useCombatState();\n\n\n const [overlayVisible, setOverlayVisible] = useState(false);\n const [severityFilters, setSeverityFilters] = useState<\n import(\"../../../types/common\").VitalPointSeverity[]\n >([]);\n const [regionFilter, setRegionFilter] =\n useState<\n import(\"../../shared/three/ui/VitalPointOverlayControlsHtml\").BodyRegionFilter\n >(\"all\");\n const [searchQuery, setSearchQuery] = useState(\"\");\n const [showLabels, setShowLabels] = useState(true);\n const [animated, setAnimated] = useState(true);\n const [scale, setScale] = useState(1.2); // Larger scale for better visibility in combat\n const [showPerformanceMonitor, setShowPerformanceMonitor] = useState(false);\n\n useEffect(() => {\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === \"v\" || e.key === \"V\") {\n setOverlayVisible((prev) => !prev);\n audio.playSFX(\"menu_select\");\n }\n if (e.key === \"F9\" && import.meta.env.DEV) {\n e.preventDefault();\n setShowPerformanceMonitor((prev) => !prev);\n }\n };\n\n window.addEventListener(\"keydown\", handleKeyDown);\n return () => {\n window.removeEventListener(\"keydown\", handleKeyDown);\n };\n }, [audio]);\n\n const { state: feedbackState, actions: feedbackActions } = useActionFeedback({\n damageNumberDuration: 1500,\n actionFeedbackDuration: 1200,\n techniqueDuration: 2000,\n comboResetTime: 2000,\n });\n\n const combatAudio = useCombatAudio();\n const { playStanceChangeSound } = combatAudio;\n\n const [matchScore, setMatchScore] = useState({ player1: 0, player2: 0 });\n const matchScoreRef = useRef(matchScore);\n\n const updateMatchScore = useCallback((winner: 0 | 1) => {\n const newScore = {\n player1:\n winner === 0\n ? matchScoreRef.current.player1 + 1\n : matchScoreRef.current.player1,\n player2:\n winner === 1\n ? matchScoreRef.current.player2 + 1\n : matchScoreRef.current.player2,\n };\n matchScoreRef.current = newScore;\n setTimeout(() => setMatchScore(newScore), 0);\n }, []);\n\n const [internalRound, setInternalRound] = useState(currentRound);\n\n const [currentTime, setCurrentTime] = useState(() => Date.now());\n\n const [hasShownMatchCountdown, setHasShownMatchCountdown] = useState(true); // Already shown (skipped)\n const [showMatchCountdown, setShowMatchCountdown] = useState(false); // Don't show\n const [showRoundStart, setShowRoundStart] = useState(false);\n const [matchCountdownComplete, setMatchCountdownComplete] = useState(true); // Already complete (skipped)\n\n const [player1Position, setPlayer1Position] = useState<Position>({\n x: arenaBounds.worldWidthMeters * -0.1, // 10% left of center (~0.8m for 8m arena)\n y: 0, // Centered\n });\n\n const [showPauseMenu, setShowPauseMenu] = useState(false);\n\n const handlePause = useCallback(() => {\n setShowPauseMenu(true);\n audio.playSFX(\"menu_select\");\n }, [audio]);\n\n const handleResume = useCallback(() => {\n setShowPauseMenu(false);\n audio.playSFX(\"menu_select\");\n }, [audio]);\n\n const handleRestart = useCallback(() => {\n\n setInternalRound(1);\n setMatchScore({ player1: 0, player2: 0 });\n matchScoreRef.current = { player1: 0, player2: 0 };\n\n combatActions.setRoundEnded(false);\n combatActions.setRoundStarted(false);\n combatActions.setRoundDisplayStatus(null);\n\n onPlayerUpdate(0, {\n health: 100,\n stamina: 100,\n ki: 100,\n consciousness: 100,\n pain: 0,\n balance: 100,\n combatState: CombatState.IDLE,\n isStunned: false,\n isBlocking: false,\n });\n onPlayerUpdate(1, {\n health: 100,\n stamina: 100,\n ki: 100,\n consciousness: 100,\n pain: 0,\n balance: 100,\n combatState: CombatState.IDLE,\n isStunned: false,\n isBlocking: false,\n });\n\n setPlayer1Position({\n x: arenaBounds.worldWidthMeters * -0.1, // 10% left of center in meters\n y: 0, // Centered\n });\n onPlayerUpdate(1, {\n position: {\n x: arenaBounds.worldWidthMeters * 0.1, // 10% right of center in meters\n y: 0, // Centered\n },\n });\n\n setShowPauseMenu(false);\n setShowRoundStart(true);\n\n audio.playSFX(\"menu_select\");\n }, [audio, combatActions, onPlayerUpdate, arenaBounds, setPlayer1Position]);\n\n const handleRoundTransitionComplete = useCallback(() => {\n if (import.meta.env.DEV) {\n console.log(\"[DEV] Round transition complete, checking match status\");\n }\n const currentScore = matchScoreRef.current;\n if (currentScore.player1 >= 2 || currentScore.player2 >= 2) {\n const matchWinner = currentScore.player1 >= 2 ? 0 : 1;\n if (import.meta.env.DEV) {\n console.log(\"[DEV] Match over, winner:\", matchWinner);\n }\n onGameEnd(matchWinner);\n return; // Don't start next round\n }\n\n combatActions.resetRoundState();\n\n setInternalRound((prev) => {\n const nextRound = prev + 1;\n if (import.meta.env.DEV) {\n console.log(\"[DEV] Incrementing round from\", prev, \"to\", nextRound);\n }\n setTimeout(() => {\n if (import.meta.env.DEV) {\n console.log(\n \"[DEV] Showing round start announcement for round\",\n nextRound,\n );\n }\n setShowRoundStart(true);\n }, ANNOUNCEMENT_FADE_OUT_DELAY);\n return nextRound;\n });\n\n onPlayerUpdate(0, {\n health: 100,\n stamina: 100,\n ki: 100,\n consciousness: 100,\n pain: 0,\n balance: 100,\n combatState: CombatState.IDLE,\n isStunned: false,\n isBlocking: false,\n });\n onPlayerUpdate(1, {\n health: 100,\n stamina: 100,\n ki: 100,\n consciousness: 100,\n pain: 0,\n balance: 100,\n combatState: CombatState.IDLE,\n isStunned: false,\n isBlocking: false,\n });\n\n setPlayer1Position({\n x: arenaBounds.worldWidthMeters * -0.1, // 10% left of center in meters\n y: 0, // Centered\n });\n onPlayerUpdate(1, {\n position: {\n x: arenaBounds.worldWidthMeters * 0.1, // 10% right of center in meters\n y: 0, // Centered\n },\n });\n }, [\n combatActions,\n onGameEnd,\n onPlayerUpdate,\n arenaBounds,\n setPlayer1Position,\n ]);\n\n const {\n showAnnouncement,\n roundWinner,\n currentRoundNumber: transitionRoundNumber,\n skipCountdown,\n startTransition,\n } = useRoundTransition(\n {\n announcementDuration: ROUND_ANNOUNCEMENT_TIMINGS.ANNOUNCEMENT_DURATION,\n countdownDuration: ROUND_ANNOUNCEMENT_TIMINGS.COUNTDOWN_DURATION,\n transitionDuration: ROUND_ANNOUNCEMENT_TIMINGS.TRANSITION_DURATION,\n },\n handleRoundTransitionComplete,\n );\n\n const player2Position = useMemo<Position>(() => {\n if (players.length >= 2 && players[1].position) {\n return players[1].position;\n }\n return {\n x: arenaBounds.worldWidthMeters * 0.1, // 10% right of center (~0.8m for 8m arena)\n y: 0, // Centered\n };\n }, [players, arenaBounds]);\n\n const playerPositions = useMemo<Position[]>(() => {\n return [player1Position, player2Position];\n }, [player1Position, player2Position]);\n\n const player1Position3D: [number, number, number] = useMemo(() => {\n return [playerPositions[0].x, 0, playerPositions[0].y];\n }, [playerPositions]);\n\n const player2Position3D: [number, number, number] = useMemo(() => {\n return [playerPositions[1].x, 0, playerPositions[1].y];\n }, [playerPositions]);\n\n\n const player2Rotation = useMemo(() => {\n const dx = player1Position3D[0] - player2Position3D[0];\n const dz = player1Position3D[2] - player2Position3D[2];\n return Math.atan2(dx, dz);\n }, [player1Position3D, player2Position3D]);\n\n const combatSystem = useMemo(() => new CombatSystem(), []);\n\n const balanceSystem = useMemo(() => new BalanceSystem(), []);\n\n const speedModifierSystem = useMemo(() => new SpeedModifierSystem(), []);\n\n const [player1SpeedModifiers, setPlayer1SpeedModifiers] = useState({\n finalSpeed: 6.0, // BASE_WALK_SPEED (6.0 m/s)\n baseSpeed: 6.0,\n finalAcceleration: 12.0, // BASE_ACCELERATION (12.0 m/s²)\n });\n const [player2SpeedModifiers, setPlayer2SpeedModifiers] = useState({\n finalSpeed: 6.0, // BASE_WALK_SPEED (6.0 m/s)\n baseSpeed: 6.0,\n finalAcceleration: 12.0, // BASE_ACCELERATION (12.0 m/s²)\n });\n\n const [player1WalkRunSpeeds, setPlayer1WalkRunSpeeds] = useState({\n walkSpeed: 6.0,\n runSpeed: 10.0,\n });\n\n useEffect(() => {\n const updateSpeedModifiers = () => {\n if (players.length >= 2) {\n const player1WalkModifiers =\n speedModifierSystem.calculateSpeedModifiers(\n players[0],\n MovementType.WALKING,\n false, // isCrouching\n );\n const player1RunModifiers = speedModifierSystem.calculateSpeedModifiers(\n players[0],\n MovementType.RUNNING,\n false, // isCrouching\n );\n\n setPlayer1SpeedModifiers({\n finalSpeed: player1WalkModifiers.finalSpeed,\n baseSpeed: player1WalkModifiers.baseSpeed,\n finalAcceleration: player1WalkModifiers.finalAcceleration,\n });\n\n setPlayer1WalkRunSpeeds({\n walkSpeed: player1WalkModifiers.finalSpeed,\n runSpeed: player1RunModifiers.finalSpeed,\n });\n\n const player2Modifiers = speedModifierSystem.calculateSpeedModifiers(\n players[1],\n MovementType.WALKING,\n false,\n );\n setPlayer2SpeedModifiers({\n finalSpeed: player2Modifiers.finalSpeed,\n baseSpeed: player2Modifiers.baseSpeed,\n finalAcceleration: player2Modifiers.finalAcceleration,\n });\n }\n };\n\n updateSpeedModifiers();\n\n const intervalId = setInterval(updateSpeedModifiers, 200);\n\n return () => clearInterval(intervalId);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [players]); // speedModifierSystem is memoized and never changes\n\n useEffect(() => {\n const updateTime = () => {\n setCurrentTime(Date.now());\n };\n\n const intervalId = setInterval(updateTime, 200);\n\n return () => clearInterval(intervalId);\n }, []);\n\n const calculateLegInjuryFactor = useCallback(\n (player: PlayerState): number => {\n if (!player.bodyPartHealth) return 0;\n\n const leftLeg = player.bodyPartHealth.legLeft ?? player.maxHealth;\n const rightLeg = player.bodyPartHealth.legRight ?? player.maxHealth;\n const maxHealth = player.maxHealth;\n\n const averageLegHealth = (leftLeg + rightLeg) / (2 * maxHealth);\n return Math.max(0, Math.min(1, 1.0 - averageLegHealth)); // 0 = healthy, 1 = critical\n },\n [],\n );\n\n const player1 = players.length > 0 ? players[0] : undefined;\n const player1Data = useMemo(() => {\n const p1 = player1 ?? createPlayerFromArchetype(PlayerArchetype.MUSA, 0);\n return {\n currentStance: p1.currentStance,\n legInjuryFactor: calculateLegInjuryFactor(p1),\n };\n }, [player1, calculateLegInjuryFactor]);\n\n const [player1AttackAnimation, setPlayer1AttackAnimation] = useState<\n string | undefined\n >(undefined);\n const [player2AttackAnimation, setPlayer2AttackAnimation] = useState<\n string | undefined\n >(undefined);\n\n const [player1TechniqueId, setPlayer1TechniqueId] = useState<\n string | undefined\n >(undefined);\n const [player2TechniqueId, setPlayer2TechniqueId] = useState<\n string | undefined\n >(undefined);\n\n const [player1Injuries, setPlayer1Injuries] = useState<readonly Injury[]>([]);\n const [player2Injuries, setPlayer2Injuries] = useState<readonly Injury[]>([]);\n\n useEffect(() => {\n return () => {\n setPlayer1Injuries([]);\n setPlayer2Injuries([]);\n };\n }, []);\n\n useEffect(() => {\n if (players.length >= 2) {\n const player1 = players[0];\n const player2 = players[1];\n\n if (\n player1?.health === player1?.maxHealth &&\n player2?.health === player2?.maxHealth\n ) {\n setPlayer1Injuries([]);\n setPlayer2Injuries([]);\n }\n }\n }, [players]);\n\n const handlePlayer1PositionChange = useCallback(\n (newPosition: Position) => {\n setPlayer1Position(newPosition);\n onPlayerUpdate(0, { position: newPosition });\n },\n [onPlayerUpdate],\n );\n\n const movementBounds = useMemo(\n () => ({\n worldWidthMeters: arenaBounds.worldWidthMeters,\n worldDepthMeters: arenaBounds.worldDepthMeters,\n }),\n [arenaBounds.worldWidthMeters, arenaBounds.worldDepthMeters],\n );\n\n\n const player1MovementTimeRef = useRef(0);\n const player1LastDirectionRef = useRef<{ x: number; y: number }>({\n x: 0,\n y: 0,\n });\n\n const [player1AccelerationBasedSpeed, setPlayer1AccelerationBasedSpeed] =\n useState(player1WalkRunSpeeds.walkSpeed);\n\n const player1IsRunning = isRunningSpeed(\n player1AccelerationBasedSpeed,\n player1WalkRunSpeeds.runSpeed,\n );\n\n const { isMoving: player1IsMoving, velocity: player1Velocity } =\n usePlayerMovement({\n enabled:\n !isPaused &&\n combatState.roundStarted &&\n !combatState.roundEnded &&\n matchCountdownComplete &&\n !showRoundStart,\n bounds: movementBounds, // Use memoized bounds object\n onPositionChange: handlePlayer1PositionChange, // Use memoized callback\n initialPositionMeters: player1Position,\n currentStance: player1Data.currentStance,\n legInjuryFactor: player1Data.legInjuryFactor,\n isRunning: player1IsRunning, // Use computed acceleration-based running state\n useTacticalSteps: false,\n maxSpeedOverride: player1AccelerationBasedSpeed,\n accelerationOverride: player1SpeedModifiers.finalAcceleration,\n });\n\n const player1Rotation = useMemo(() => {\n if (\n player1IsMoving &&\n player1Velocity &&\n (player1Velocity.x !== 0 || player1Velocity.y !== 0)\n ) {\n const movementRotation = Math.atan2(player1Velocity.x, player1Velocity.y);\n return movementRotation;\n } else {\n const dx = player2Position3D[0] - player1Position3D[0];\n const dz = player2Position3D[2] - player1Position3D[2];\n const targetRotation = Math.atan2(dx, dz);\n return targetRotation;\n }\n }, [player1IsMoving, player1Velocity, player1Position3D, player2Position3D]);\n\n const handleAttackRef = useRef<(() => void) | null>(null);\n\n const player1AnimationRef = useRef<ReturnType<\n typeof usePlayerAnimation\n > | null>(null);\n\n const validPlayersRefForAnimation = useRef<[PlayerState, PlayerState] | null>(\n null,\n );\n\n const player1HitTriggerFrameRef = useRef<number>(6);\n const player1AttackHitFiredRef = useRef<boolean>(false);\n\n const [player1AttackDuration, setPlayer1AttackDuration] =\n useState<number>(0.55);\n const [player2AttackDuration, setPlayer2AttackDuration] =\n useState<number>(0.55);\n\n const clearPlayer1AttackAnimation = useRef<() => void>(() => {\n setPlayer1AttackAnimation(undefined);\n setPlayer1TechniqueId(undefined);\n });\n const clearPlayer2AttackAnimation = useRef<() => void>(() => {\n setPlayer2AttackAnimation(undefined);\n setPlayer2TechniqueId(undefined);\n });\n\n const player1AnimationEvents = useMemo<AnimationEvents>(\n () => ({\n onFrame: (frame, state) => {\n if (\n state === AnimationState.ATTACK &&\n frame >= player1HitTriggerFrameRef.current &&\n !player1AttackHitFiredRef.current\n ) {\n player1AttackHitFiredRef.current = true;\n handleAttackRef.current?.();\n }\n },\n onAnimationComplete: (state) => {\n if (\n state === AnimationState.ATTACK ||\n state === AnimationState.DEFEND\n ) {\n combatActions.setExecutingTechnique(false);\n if (state === AnimationState.ATTACK) {\n clearPlayer1AttackAnimation.current();\n }\n } else if (state === AnimationState.STANCE_CHANGE) {\n audio.playSFX(\"menu_select\");\n const players = validPlayersRefForAnimation.current;\n const currentStance = players?.[0]?.currentStance;\n if (currentStance && player1AnimationRef.current) {\n player1AnimationRef.current.transitionToStanceGuard(currentStance);\n }\n }\n },\n }),\n [combatActions, audio],\n );\n\n const player1Animation = usePlayerAnimation({\n events: player1AnimationEvents,\n });\n\n useEffect(() => {\n player1AnimationRef.current = player1Animation;\n }, [player1Animation]);\n\n const player2Animation = usePlayerAnimation({\n events: {\n onFrame: (frame, state) => {\n if (state === AnimationState.ATTACK && frame === 6) { /* attack frame hook */ }\n },\n onAnimationComplete: (state) => {\n if (state === AnimationState.ATTACK) {\n clearPlayer2AttackAnimation.current();\n }\n },\n },\n });\n\n const prevPlayer1IsMovingRef = useRef<boolean>(player1IsMoving);\n const prevPlayer1IsRunningRef = useRef<boolean>(player1IsRunning);\n useEffect(() => {\n const movementChanged = prevPlayer1IsMovingRef.current !== player1IsMoving;\n const runningChanged = prevPlayer1IsRunningRef.current !== player1IsRunning;\n\n if (movementChanged || runningChanged) {\n if (player1IsMoving) {\n const targetState = player1IsRunning\n ? AnimationState.RUN\n : AnimationState.WALK;\n if (player1Animation.currentState !== targetState) {\n player1Animation.transitionTo(targetState);\n }\n } else if (\n player1Animation.currentState === AnimationState.WALK ||\n player1Animation.currentState === AnimationState.RUN\n ) {\n player1Animation.transitionToStanceGuard(player1Data.currentStance);\n }\n prevPlayer1IsMovingRef.current = player1IsMoving;\n prevPlayer1IsRunningRef.current = player1IsRunning;\n }\n }, [\n player1IsMoving,\n player1IsRunning,\n player1Animation,\n player1Data.currentStance,\n ]);\n\n const MOVEMENT_DETECTION_THRESHOLD = 0.5;\n\n const player2Stance = useMemo(() => {\n return players[1]?.currentStance ?? TrigramStance.GEON;\n }, [players]);\n\n const prevPlayer2PositionRef = useRef(player2Position);\n useEffect(() => {\n const currentPos = playerPositions[1];\n const prevPos = prevPlayer2PositionRef.current;\n\n const isMoving =\n Math.abs(currentPos.x - prevPos.x) > MOVEMENT_DETECTION_THRESHOLD ||\n Math.abs(currentPos.y - prevPos.y) > MOVEMENT_DETECTION_THRESHOLD;\n\n if (isMoving) {\n if (\n player2Animation.currentState !== AnimationState.WALK &&\n player2Animation.currentState !== AnimationState.ATTACK\n ) {\n player2Animation.transitionTo(AnimationState.WALK);\n }\n } else {\n if (player2Animation.currentState === AnimationState.WALK) {\n player2Animation.transitionToStanceGuard(player2Stance);\n }\n }\n\n prevPlayer2PositionRef.current = currentPos;\n }, [playerPositions, player2Animation, player2Stance]);\n\n const validPlayers = useMemo((): [PlayerState, PlayerState] => {\n if (players.length === 0) {\n const player1 = createPlayerFromArchetype(PlayerArchetype.MUSA, 0);\n const player2 = createPlayerFromArchetype(PlayerArchetype.AMSALJA, 1);\n\n return [\n { ...player1, position: playerPositions[0] },\n { ...player2, position: playerPositions[1] },\n ];\n }\n\n const player1 = players[0];\n const player2 =\n players[1] ?? createPlayerFromArchetype(PlayerArchetype.AMSALJA, 1);\n\n return [\n { ...player1, position: playerPositions[0] },\n { ...player2, position: playerPositions[1] },\n ];\n }, [players, playerPositions]);\n\n const validPlayersRef = useRef<[PlayerState, PlayerState]>(validPlayers);\n useEffect(() => {\n validPlayersRef.current = validPlayers;\n validPlayersRefForAnimation.current = validPlayers;\n }, [validPlayers]);\n\n const getTechniqueAnimationType = useCallback(\n (techniqueId: string | undefined): AnimationType | undefined => {\n if (!techniqueId) return undefined;\n\n return getAnimationTypeForTechnique(techniqueId);\n },\n [],\n );\n\n const {\n player1Position: player1PositionWithAttackMovement,\n player2Position: player2PositionWithAttackMovement,\n } = useCombatAttackMovement({\n player1Attacking: player1Animation.currentState === AnimationState.ATTACK,\n player1AnimationType: getTechniqueAnimationType(player1TechniqueId),\n player1Stance: player1Data.currentStance,\n player1BasePosition: player1Position3D,\n player1AnimationDuration: player1AttackDuration,\n player2Attacking: player2Animation.currentState === AnimationState.ATTACK,\n player2AnimationType: getTechniqueAnimationType(player2TechniqueId),\n player2Stance: validPlayers[1].currentStance,\n player2BasePosition: player2Position3D,\n player2AnimationDuration: player2AttackDuration,\n });\n\n const [player1LocalStance, setPlayer1LocalStance] = useState<TrigramStance>(\n validPlayers[0].currentStance,\n );\n\n useEffect(() => {\n setPlayer1LocalStance(validPlayers[0].currentStance);\n }, [validPlayers]);\n\n const player1WithLocalStance = useMemo(\n (): PlayerState => ({\n ...validPlayers[0],\n currentStance: player1LocalStance,\n }),\n [validPlayers, player1LocalStance],\n );\n\n const startTransitionRef = useRef(startTransition);\n const internalRoundRef = useRef(internalRound);\n useEffect(() => {\n startTransitionRef.current = startTransition;\n internalRoundRef.current = internalRound;\n }, [startTransition, internalRound]);\n\n const addCombatMessage = useCallback(\n (korean: string, english: string) => {\n const message = `${korean} | ${english}`;\n combatActions.addCombatMessage(message);\n },\n [combatActions],\n );\n\n const handleTimeUp = useCallback(() => {\n if (!combatState.roundEnded) {\n combatActions.setRoundEnded(true);\n addCombatMessage(\"시간 종료!\", \"Time's Up!\");\n\n const currentPlayers = validPlayersRef.current;\n const player1Health = currentPlayers[0].health;\n const player2Health = currentPlayers[1].health;\n\n if (player1Health > player2Health) {\n updateMatchScore(0);\n startTransitionRef.current(currentPlayers[0], internalRoundRef.current); // Player 1 wins round\n } else if (player2Health > player1Health) {\n updateMatchScore(1);\n startTransitionRef.current(currentPlayers[1], internalRoundRef.current); // Player 2 wins round\n } else {\n startTransitionRef.current(null, internalRoundRef.current);\n }\n }\n }, [\n combatState.roundEnded,\n combatActions,\n addCombatMessage,\n updateMatchScore,\n ]);\n\n const handleTimeUpRef = useRef(handleTimeUp);\n useEffect(() => {\n handleTimeUpRef.current = handleTimeUp;\n }, [handleTimeUp]);\n\n const timerResetKey = `round-${internalRound}`;\n\n const timerState = useCombatTimer({\n initialTime: Math.max(0, timeRemaining),\n isPaused:\n isPaused ||\n !combatState.roundStarted ||\n combatState.roundEnded ||\n !matchCountdownComplete ||\n showRoundStart,\n onTimeUp: useCallback(() => handleTimeUpRef.current(), []),\n warningThreshold: 10,\n urgentThreshold: 5,\n resetKey: timerResetKey,\n });\n\n const startRound = useCallback(() => {\n if (import.meta.env.DEV) {\n console.log(\"[DEV] Starting round, setting roundStarted=true\");\n }\n combatActions.setRoundStarted(true);\n combatActions.setRoundEnded(false); // Ensure roundEnded is false\n addCombatMessage(\"라운드 시작!\", \"Round Start!\");\n\n const player = validPlayers[0];\n if (player?.archetype) {\n const playerArchetype = player.archetype.toLowerCase();\n combatAudio.playArchetypeMusic(playerArchetype, 2000);\n } else {\n combatAudio.playCombatMusic(2000);\n }\n }, [combatActions, addCombatMessage, validPlayers, combatAudio]);\n\n const hasAutoStartedRef = useRef(false);\n\n useEffect(() => {\n if (matchCountdownComplete && !hasAutoStartedRef.current) {\n hasAutoStartedRef.current = true;\n combatActions.setRoundStarted(true);\n addCombatMessage(\"라운드 시작!\", \"Round Start!\");\n\n const player = validPlayers[0];\n if (player?.archetype) {\n const playerArchetype = player.archetype.toLowerCase();\n combatAudio.playArchetypeMusic(playerArchetype, 2000);\n } else {\n combatAudio.playCombatMusic(2000);\n }\n }\n }, [\n matchCountdownComplete,\n combatActions,\n addCombatMessage,\n validPlayers,\n combatAudio,\n ]);\n\n const adaptiveDifficulty = useMemo(() => new AdaptiveDifficulty(), []);\n\n useEffect(() => {\n try {\n const savedMetrics = localStorage.getItem(\"ai_difficulty_metrics\");\n if (savedMetrics) {\n adaptiveDifficulty.importMetrics(savedMetrics);\n }\n } catch (err) {\n console.warn(\"Failed to load AI difficulty metrics:\", err);\n }\n\n return () => {\n try {\n const metrics = adaptiveDifficulty.exportMetrics();\n localStorage.setItem(\"ai_difficulty_metrics\", metrics);\n } catch (err) {\n console.warn(\"Failed to save AI difficulty metrics:\", err);\n }\n };\n }, [adaptiveDifficulty]);\n\n const aiPersonality = useMemo(\n () => getPersonalityByArchetype(validPlayers[1].archetype),\n [validPlayers],\n );\n\n const handleAIStanceChange = useCallback(\n (stance: TrigramStance) => {\n const currentStance = validPlayers[1].currentStance;\n\n player2Animation.transitionToStanceChange(currentStance, stance);\n\n onPlayerUpdate(1, { currentStance: stance });\n addCombatMessage(\n `AI 자세 변경: ${stance}`,\n `AI Stance Change: ${stance}`,\n );\n },\n [validPlayers, player2Animation, onPlayerUpdate, addCombatMessage],\n );\n\n const handleEffectComplete = useCallback(\n (effectId: string) => {\n combatActions.removeHitEffect(effectId);\n },\n [combatActions],\n );\n\n const createHitEffect = useCallback(\n (\n id: string,\n type: HitEffectType,\n position: Position,\n intensity: number,\n ): HitEffect => ({\n id,\n type,\n attackerId: \"player1\",\n defenderId: \"player2\",\n timestamp: Date.now(),\n duration: 1000,\n position,\n intensity,\n startTime: Date.now(),\n }),\n [],\n );\n\n const addHitEffect = useCallback(\n (type: HitEffectType, position: Position, intensity: number = 1) => {\n const effect = createHitEffect(\n `effect_${Date.now()}`,\n type,\n position,\n intensity,\n );\n combatActions.addHitEffect(effect);\n },\n [createHitEffect, combatActions],\n );\n\n const handlePlayerPositionUpdate = useCallback(\n (playerIndex: number, position: Position) => {\n if (playerIndex === 0) {\n setPlayer1Position(position);\n onPlayerUpdate(0, { position });\n } else if (playerIndex === 1) {\n onPlayerUpdate(1, { position });\n }\n },\n [onPlayerUpdate, setPlayer1Position],\n );\n\n const handleInjuryCreated = useCallback(\n (injury: Injury, targetPlayerIndex: number) => {\n const updateInjuries = (prev: readonly Injury[]): readonly Injury[] => {\n const recentHitTime = 5000; // 5 seconds\n const now = Date.now();\n\n const recentHit = prev.find(\n (existing) =>\n existing.region === injury.region &&\n now - existing.timestamp < recentHitTime &&\n existing.type === InjuryType.BRUISE &&\n injury.type === InjuryType.BRUISE,\n );\n\n if (recentHit) {\n const newHitCount = recentHit.hitCount + 1;\n const escalatedSeverity = Math.min(1.0, recentHit.severity + 0.15);\n\n return prev.map((existing) =>\n existing.id === recentHit.id\n ? {\n ...existing,\n hitCount: newHitCount,\n severity: escalatedSeverity,\n timestamp: now, // Update timestamp for progressive tracking\n }\n : existing,\n );\n }\n\n return [...prev, injury];\n };\n\n if (targetPlayerIndex === 0) {\n setPlayer1Injuries(updateInjuries);\n } else if (targetPlayerIndex === 1) {\n setPlayer2Injuries(updateInjuries);\n }\n },\n [],\n );\n\n const {\n handleAttack,\n handleDefend,\n handleStanceSwitch,\n handleStanceSideSwitch,\n handleAIAttack,\n handleAIDefend,\n handleAITechnique,\n moveAIPlayer,\n } = useCombatActions({\n validPlayers,\n playerPositions: [playerPositions[0], playerPositions[1]],\n combatState,\n combatActions,\n combatSystem,\n onPlayerUpdate,\n onPlayerPositionUpdate: handlePlayerPositionUpdate,\n onLateralityUpdate: (playerIndex, laterality) => {\n combatActions.setPlayerLateralityIndex(playerIndex as 0 | 1, laterality);\n },\n onInjuryCreated: handleInjuryCreated,\n addCombatMessage,\n addHitEffect,\n arenaBounds,\n combatAudio,\n playerAnimations: {\n player1: player1Animation,\n player2: player2Animation,\n },\n });\n\n useEffect(() => {\n handleAttackRef.current = handleAttack;\n }, [handleAttack]);\n\n const techniqueSelection = useTechniqueSelection({\n player: player1WithLocalStance,\n enabled:\n !isPaused &&\n combatState.roundStarted &&\n !combatState.roundEnded &&\n matchCountdownComplete &&\n !showRoundStart,\n onTechniqueExecute: useCallback(\n (technique: Technique) => {\n feedbackActions.showTechnique(\n technique.name.korean,\n technique.name.english,\n );\n\n const animationName = resolveTechniqueAnimation(technique);\n setPlayer1AttackAnimation(animationName);\n\n setPlayer1TechniqueId(technique.id);\n\n const skeletalAnim = getAnimation(animationName);\n const attackDuration = skeletalAnim?.duration ?? 0.55;\n\n const attackFrames = Math.max(1, Math.round(attackDuration * 60));\n player1HitTriggerFrameRef.current = Math.round(attackFrames * 0.4);\n player1AttackHitFiredRef.current = false;\n setPlayer1AttackDuration(attackDuration);\n player1Animation.transitionToAttack(attackDuration);\n combatActions.setExecutingTechnique(true);\n\n onPlayerUpdate(0, {\n stamina: Math.max(0, validPlayers[0].stamina - technique.staminaCost),\n ki: Math.max(0, validPlayers[0].ki - technique.kiCost),\n });\n\n handleAttack(technique);\n\n addCombatMessage(\n `${technique.name.korean} 사용!`,\n `Used ${technique.name.english}!`,\n );\n },\n [\n validPlayers,\n onPlayerUpdate,\n feedbackActions,\n handleAttack,\n addCombatMessage,\n player1Animation,\n combatActions,\n ],\n ),\n });\n\n const cooldownsMap = useMemo(() => {\n const map = new Map<string, number>();\n techniqueSelection.activeCooldowns.forEach((cd) => {\n map.set(cd.techniqueId, cd.remaining);\n });\n return map;\n }, [techniqueSelection.activeCooldowns]);\n\n const [previousStance, setPreviousStance] = useState<number>(0);\n\n const currentPlayerStance = validPlayers[0].currentStance;\n const currentStanceIndex = useMemo(() => {\n return STANCE_INDEX_MAP.get(currentPlayerStance) ?? 0;\n }, [currentPlayerStance]);\n\n const handleStanceChangeWithAnimation = useCallback(\n (newStance: TrigramStance) => {\n const currentStance = validPlayers[0].currentStance;\n\n const success = player1Animation.transitionToStanceGuard(newStance);\n\n if (success) {\n const prevStance = STANCE_INDEX_MAP.get(currentStance) ?? 0;\n setPreviousStance(prevStance);\n\n setPlayer1LocalStance(newStance);\n\n handleStanceSwitch(newStance);\n\n playStanceChangeSound();\n }\n },\n [validPlayers, player1Animation, handleStanceSwitch, playStanceChangeSound],\n );\n\n const player1Health = validPlayers[0].health;\n const player2Health = validPlayers[1].health;\n\n const lastPlayer2HealthRef = useRef(player2Health);\n useEffect(() => {\n const currentHealth = player2Health;\n const previousHealth = lastPlayer2HealthRef.current;\n const damageDone = previousHealth - currentHealth;\n\n if (damageDone > 0 && combatState.roundStarted && !combatState.roundEnded) {\n const getDamageType = (): \"critical\" | \"vital\" | \"normal\" => {\n if (damageDone >= 25) return \"critical\";\n if (damageDone >= 20) return \"vital\";\n return \"normal\";\n };\n const damageType = getDamageType();\n\n feedbackActions.addDamageNumber(\n Math.round(damageDone),\n playerPositions[1],\n damageType,\n );\n\n feedbackActions.incrementCombo();\n\n if (damageType === \"critical\") {\n feedbackActions.addActionFeedback(\n \"critical\",\n \"Critical!\",\n \"치명타!\",\n playerPositions[0],\n );\n }\n }\n\n lastPlayer2HealthRef.current = currentHealth;\n }, [\n player2Health,\n validPlayers,\n playerPositions,\n feedbackActions,\n combatState.roundStarted,\n combatState.roundEnded,\n ]);\n\n const lastPlayer1HealthRef = useRef(player1Health);\n useEffect(() => {\n const currentHealth = player1Health;\n const previousHealth = lastPlayer1HealthRef.current;\n const damageDone = previousHealth - currentHealth;\n\n if (damageDone > 0 && combatState.roundStarted && !combatState.roundEnded) {\n const damageType =\n damageDone >= 20 ? (\"critical\" as const) : (\"normal\" as const);\n feedbackActions.addDamageNumber(\n Math.round(damageDone),\n playerPositions[0],\n damageType,\n );\n }\n\n lastPlayer1HealthRef.current = currentHealth;\n }, [\n player1Health,\n validPlayers,\n playerPositions,\n feedbackActions,\n combatState.roundStarted,\n combatState.roundEnded,\n ]);\n\n const handleAttackWithFeedback = useCallback(() => {\n const basicTechnique = techniqueSelection.availableTechniques[0];\n const animationName = basicTechnique\n ? resolveTechniqueAnimation(basicTechnique)\n : \"jab\";\n setPlayer1AttackAnimation(animationName);\n if (basicTechnique?.id) {\n setPlayer1TechniqueId(basicTechnique.id);\n }\n\n const success = player1Animation.transitionTo(AnimationState.ATTACK);\n if (success) {\n combatActions.setExecutingTechnique(true);\n } else {\n console.warn(\n \"Attack animation transition failed; executing attack logic directly.\",\n );\n handleAttack();\n }\n }, [\n player1Animation,\n combatActions,\n handleAttack,\n techniqueSelection.availableTechniques,\n ]);\n\n const handleDefendWithFeedback = useCallback(() => {\n const defenderPos = playerPositions[0];\n const success = player1Animation.transitionTo(AnimationState.DEFEND);\n if (success) {\n handleDefend();\n feedbackActions.addActionFeedback(\n \"blocked\",\n \"Blocked\",\n \"방어!\",\n defenderPos,\n );\n } else {\n console.warn(\n \"Defend animation transition failed; executing defend logic directly.\",\n );\n handleDefend();\n feedbackActions.addActionFeedback(\n \"blocked\",\n \"Blocked\",\n \"방어!\",\n defenderPos,\n );\n }\n }, [handleDefend, playerPositions, feedbackActions, player1Animation]);\n\n /**\n * Helper function to execute fallback recovery animation\n * when a specific recovery type cannot be performed.\n *\n * Determines the appropriate recovery type based on ground state\n * and transitions to that animation.\n *\n * @korean 대체회복실행\n */\n const executeFallbackRecovery = useCallback(() => {\n const groundState = balanceSystem.getGroundState(\n player1Animation.currentState,\n );\n if (groundState) {\n const recoveryType = determineRecoveryType(groundState);\n const animationState = getRecoveryAnimationState(recoveryType);\n player1Animation.transitionTo(animationState as AnimationState);\n }\n }, [balanceSystem, player1Animation]);\n\n const { queuedInputs, showHints } = useKeyboardControls({\n onStanceChange: useCallback(\n (stanceIndex: number) => {\n const stance = TRIGRAM_STANCES_ORDER[stanceIndex];\n if (stance) {\n handleStanceChangeWithAnimation(stance);\n }\n },\n [handleStanceChangeWithAnimation],\n ),\n onAction: useCallback(\n (action: string) => {\n switch (action) {\n case \"attack\":\n techniqueSelection.executeTechnique();\n break;\n case \"block\":\n handleDefendWithFeedback();\n break;\n case \"recovery_quick\": {\n executeFallbackRecovery();\n break;\n }\n case \"recovery_roll\": {\n const player1 = players[0];\n if (balanceSystem.canRecoverWithType(player1, \"roll_recovery\")) {\n const updatedPlayer = balanceSystem.applyRecoveryCost(\n player1,\n \"roll_recovery\",\n );\n onPlayerUpdate(0, { stamina: updatedPlayer.stamina });\n player1Animation.transitionTo(AnimationState.RECOVERY_ROLL);\n } else {\n audio.playSFX(\"menu_error\");\n const player1Pos = playerPositions[0];\n feedbackActions.addActionFeedback(\n \"blocked\",\n \"Not enough stamina!\",\n \"체력 부족!\",\n player1Pos,\n );\n executeFallbackRecovery();\n }\n break;\n }\n case \"recovery_defensive\": {\n player1Animation.transitionTo(AnimationState.RECOVERY_DEFENSIVE);\n break;\n }\n\n case \"footwork_circular_left\":\n case \"footwork_circular_right\":\n case \"footwork_slide_forward\":\n case \"footwork_slide_back\":\n case \"footwork_pivot_left\":\n case \"footwork_pivot_right\":\n case \"footwork_shuffle\":\n player1Animation.transitionTo(action as AnimationState);\n break;\n\n case \"stance_side_switch\":\n player1Animation.transitionTo(AnimationState.STANCE_SIDE_SWITCH);\n break;\n\n }\n },\n [\n techniqueSelection,\n handleDefendWithFeedback,\n executeFallbackRecovery,\n balanceSystem,\n player1Animation,\n players,\n onPlayerUpdate,\n audio,\n feedbackActions,\n playerPositions,\n ],\n ),\n enabled:\n !isPaused &&\n !showPauseMenu &&\n combatState.roundStarted &&\n !combatState.roundEnded &&\n matchCountdownComplete &&\n !showRoundStart &&\n !combatState.isExecutingTechnique,\n currentStance: currentStanceIndex,\n playSFX: audio.playSFX,\n currentAnimationState: player1Animation.currentState,\n });\n\n const [stanceWheelExpanded, setStanceWheelExpanded] = useState(false);\n const activeMobileKeyRef = useRef<string | null>(null);\n\n /**\n * Mobile touch control handler - Converts VirtualDPad touch inputs to keyboard events\n *\n * Dispatches synthetic KeyboardEvents with proper properties to ensure compatibility\n * with usePlayerMovement hook. The synthetic events include:\n * - key: The character key (w/a/s/d)\n * - code: The physical key code (KeyW/KeyA/KeyS/KeyD)\n * - bubbles: true - Allows event to propagate through DOM\n * - cancelable: true - Allows event to be prevented\n *\n * These properties are essential for the keyboard event listeners in inputSystem.ts\n * to properly recognize and process the movement commands.\n *\n * @param direction - The D-pad direction or null\n * @param eventType - 'start' for press, 'end' for release\n */\n const handleMobileMove = useCallback(\n (direction: Direction | null, eventType: DPadEventType) => {\n const directionMap: Record<Direction, string> = {\n up: \"w\",\n \"up-right\": \"w\", // Diagonal simplified to primary direction\n right: \"d\",\n \"down-right\": \"s\",\n down: \"s\",\n \"down-left\": \"s\",\n left: \"a\",\n \"up-left\": \"w\",\n };\n\n if (eventType === \"start\" && direction) {\n if (\n activeMobileKeyRef.current &&\n activeMobileKeyRef.current !== directionMap[direction]\n ) {\n const prevKey = activeMobileKeyRef.current;\n window.dispatchEvent(\n new KeyboardEvent(\"keyup\", {\n key: prevKey,\n code: `Key${prevKey.toUpperCase()}`,\n bubbles: true,\n cancelable: true,\n }),\n );\n }\n\n const key = directionMap[direction];\n activeMobileKeyRef.current = key;\n window.dispatchEvent(\n new KeyboardEvent(\"keydown\", {\n key,\n code: `Key${key.toUpperCase()}`,\n bubbles: true,\n cancelable: true,\n }),\n );\n } else if (eventType === \"end\") {\n if (activeMobileKeyRef.current) {\n const key = activeMobileKeyRef.current;\n window.dispatchEvent(\n new KeyboardEvent(\"keyup\", {\n key,\n code: `Key${key.toUpperCase()}`,\n bubbles: true,\n cancelable: true,\n }),\n );\n activeMobileKeyRef.current = null;\n }\n }\n },\n [],\n );\n\n const handleMobileAttack = useCallback(() => {\n techniqueSelection.executeTechnique();\n }, [techniqueSelection]);\n\n const handleMobileBlock = useCallback(\n (eventType: ButtonEventType) => {\n if (eventType === \"start\") {\n handleDefendWithFeedback();\n }\n },\n [handleDefendWithFeedback],\n );\n\n const handleMobileStanceChange = useCallback(\n (stanceIndex: number) => {\n const stance = TRIGRAM_STANCES_ORDER[stanceIndex];\n if (stance) {\n handleStanceChangeWithAnimation(stance);\n }\n },\n [handleStanceChangeWithAnimation],\n );\n\n const handleMobileGesture = useCallback(\n (gesture: GestureEvent) => {\n switch (gesture.type) {\n case \"swipe-right\":\n window.dispatchEvent(new KeyboardEvent(\"keydown\", { key: \"d\" }));\n setTimeout(() => {\n window.dispatchEvent(new KeyboardEvent(\"keyup\", { key: \"d\" }));\n }, 100);\n break;\n case \"swipe-left\":\n window.dispatchEvent(new KeyboardEvent(\"keydown\", { key: \"a\" }));\n setTimeout(() => {\n window.dispatchEvent(new KeyboardEvent(\"keyup\", { key: \"a\" }));\n }, 100);\n break;\n case \"swipe-up\":\n techniqueSelection.executeTechnique();\n break;\n case \"swipe-down\":\n techniqueSelection.executeTechnique();\n break;\n case \"two-finger-tap\":\n audio.playSFX(\"menu_select\");\n break;\n }\n },\n [techniqueSelection, audio],\n );\n\n const toggleStanceWheel = useCallback(() => {\n setStanceWheelExpanded((prev) => !prev);\n }, []);\n\n const mobileControlsEnabled =\n isMobile &&\n !isPaused &&\n !showPauseMenu &&\n combatState.roundStarted &&\n !combatState.roundEnded &&\n matchCountdownComplete &&\n !showRoundStart &&\n !combatState.isExecutingTechnique;\n\n\n useEffect(() => {\n if (isPaused) return;\n\n if (timeRemaining <= 0 && !combatState.roundEnded) {\n combatActions.setRoundEnded(true);\n combatActions.setRoundStarted(false);\n combatActions.setRoundDisplayStatus(\"end\");\n\n combatAudio.stopCombatMusic(1000);\n\n const winner = validPlayers[0].health > validPlayers[1].health ? 0 : 1;\n const roundWinner = validPlayers[winner];\n\n updateMatchScore(winner);\n\n addCombatMessage(\"라운드 종료!\", \"Round Over!\");\n\n setTimeout(() => {\n startTransition(roundWinner, internalRound);\n }, 1500);\n }\n }, [\n timeRemaining,\n combatState.roundEnded,\n combatState.roundStarted,\n validPlayers,\n onGameEnd,\n addCombatMessage,\n internalRound,\n isPaused,\n combatActions,\n combatAudio,\n startTransition,\n updateMatchScore,\n ]);\n\n const executeAIActionCallbackRef = useRef<\n | ((\n action: string,\n targetPos?: Position,\n selectedTechnique?: KoreanTechnique,\n targetVitalPoint?: string,\n ) => void)\n | undefined\n >(undefined);\n\n const { updateDifficultyTarget } = useAICombat({\n player: validPlayers[1],\n opponent: validPlayers[0],\n personality: aiPersonality,\n adaptiveDifficulty,\n isPaused,\n roundStarted: combatState.roundStarted,\n roundEnded: combatState.roundEnded,\n arenaBounds,\n onExecuteAction: (action, targetPos, selectedTechnique, targetVitalPoint) =>\n executeAIActionCallbackRef.current?.(\n action,\n targetPos,\n selectedTechnique,\n targetVitalPoint,\n ),\n onStanceChange: handleAIStanceChange,\n onLateralityChange: () => handleStanceSideSwitch(1), // AI player (index 1)\n playerLaterality: combatState.playerLaterality[1], // AI's own laterality\n opponentLaterality: combatState.playerLaterality[0], // Opponent (human) laterality\n });\n\n const currentDifficultyTier = useMemo(\n () => adaptiveDifficulty.getDifficultyTier(),\n [adaptiveDifficulty],\n );\n\n useEffect(() => {\n if (!combatState.roundEnded || internalRound < 1) {\n return;\n }\n\n const roundsCompleted = internalRound;\n if (roundsCompleted % 2 === 0) {\n const player1 = validPlayersRef.current[0];\n\n adaptiveDifficulty.updateSkillMetrics({\n hitsLanded: player1.hitsLanded ?? 0,\n totalAttacks: (player1.hitsLanded ?? 0) + (player1.misses ?? 0),\n combosExecuted: 0, // TODO (Phase 2): Track combo count in PlayerState\n perfectBlockCount: 0, // TODO (Phase 2): Track perfect blocks in PlayerState\n avgReactionTimeMs: 600, // TODO (Phase 2): Track player reaction time\n vitalPointsHit: 0, // TODO (Phase 2): Track vital point hits\n effectiveStanceChanges: 0, // TODO (Phase 2): Track stance changes\n damageDealt: player1.totalDamageDealt ?? 0,\n damageTaken: player1.totalDamageReceived ?? 0,\n });\n\n const newParams = adaptiveDifficulty.getDifficultyParameters();\n updateDifficultyTarget(newParams);\n\n if (import.meta.env.DEV) {\n const tier = adaptiveDifficulty.getDifficultyTier();\n console.log(\n `[DEV] Difficulty adjusted after round ${roundsCompleted}, new tier: ${tier}`,\n );\n }\n }\n }, [\n combatState.roundEnded,\n internalRound,\n adaptiveDifficulty,\n updateDifficultyTarget,\n ]);\n\n const executeAIActionCallback = useCallback(\n (\n action: string,\n targetPos?: Position,\n selectedTechnique?: KoreanTechnique,\n targetVitalPoint?: string,\n ) => {\n const aiStance = validPlayers[1]?.currentStance ?? TrigramStance.GEON;\n const aiFallbackTechnique = TRIGRAM_TECHNIQUES[aiStance]?.[0];\n const aiFallbackAnim = aiFallbackTechnique\n ? resolveTechniqueAnimation(aiFallbackTechnique)\n : \"jab\";\n switch (action) {\n case \"attack\":\n if (selectedTechnique) {\n const p2AttackAnimName = resolveTechniqueAnimation(selectedTechnique);\n setPlayer2AttackAnimation(p2AttackAnimName);\n\n if (selectedTechnique.id) {\n setPlayer2TechniqueId(selectedTechnique.id);\n }\n const p2AttackAnim = getAnimation(p2AttackAnimName);\n const p2AttackDur = p2AttackAnim?.duration ?? 0.55;\n setPlayer2AttackDuration(p2AttackDur);\n player2Animation.transitionToAttack(p2AttackDur);\n } else {\n setPlayer2AttackAnimation(aiFallbackAnim);\n if (aiFallbackTechnique?.id) {\n setPlayer2TechniqueId(aiFallbackTechnique.id);\n }\n const p2FallbackAnim = getAnimation(aiFallbackAnim);\n const p2FallbackDur = p2FallbackAnim?.duration ?? 0.55;\n setPlayer2AttackDuration(p2FallbackDur);\n player2Animation.transitionToAttack(p2FallbackDur);\n }\n handleAIAttack(selectedTechnique, targetVitalPoint);\n break;\n case \"defend\":\n player2Animation.transitionTo(AnimationState.DEFEND);\n handleAIDefend();\n break;\n case \"technique\":\n case \"combo\":\n if (selectedTechnique) {\n const p2TechAnimName = resolveTechniqueAnimation(selectedTechnique);\n setPlayer2AttackAnimation(p2TechAnimName);\n\n if (selectedTechnique.id) {\n setPlayer2TechniqueId(selectedTechnique.id);\n }\n const p2TechAnim = getAnimation(p2TechAnimName);\n const p2TechDur = p2TechAnim?.duration ?? 0.6;\n setPlayer2AttackDuration(p2TechDur);\n player2Animation.transitionToAttack(p2TechDur);\n } else {\n setPlayer2AttackAnimation(aiFallbackAnim);\n if (aiFallbackTechnique?.id) {\n setPlayer2TechniqueId(aiFallbackTechnique.id);\n }\n const p2FallbackAnim = getAnimation(aiFallbackAnim);\n const p2FallbackDur = p2FallbackAnim?.duration ?? 0.6;\n setPlayer2AttackDuration(p2FallbackDur);\n player2Animation.transitionToAttack(p2FallbackDur);\n }\n handleAITechnique(selectedTechnique, targetVitalPoint);\n break;\n case \"approach\":\n case \"retreat\":\n case \"circle\":\n if (targetPos) {\n moveAIPlayer(targetPos);\n }\n break;\n case \"feint\":\n {\n const playerPos = validPlayers[0].position;\n const feintOffsetMeters = 0.5;\n const feintPos = {\n x: playerPos.x + (Math.random() - 0.5) * feintOffsetMeters,\n y: playerPos.y + (Math.random() - 0.5) * feintOffsetMeters,\n };\n moveAIPlayer(feintPos);\n addCombatMessage(\"AI 페인트\", \"AI Feint\");\n\n setTimeout(() => {\n if (\n !combatState.roundEnded &&\n combatState.roundStarted &&\n validPlayers.length >= 2\n ) {\n const currentPlayerPos = validPlayers[0].position;\n const currentAiPos = validPlayers[1].position;\n const dx = currentAiPos.x - currentPlayerPos.x;\n const dy = currentAiPos.y - currentPlayerPos.y;\n const dist = Math.sqrt(dx * dx + dy * dy) || 1;\n const retreatDistanceMeters = 0.8;\n const halfWidth = arenaBounds.worldWidthMeters / 2;\n const halfDepth = arenaBounds.worldDepthMeters / 2;\n const retreatPos = {\n x: Math.max(\n -halfWidth + 0.5, // 0.5m from edge\n Math.min(\n halfWidth - 0.5,\n currentPlayerPos.x + (dx / dist) * retreatDistanceMeters,\n ),\n ),\n y: Math.max(\n -halfDepth + 0.5, // 0.5m from edge\n Math.min(\n halfDepth - 0.5,\n currentPlayerPos.y + (dy / dist) * retreatDistanceMeters,\n ),\n ),\n };\n moveAIPlayer(retreatPos);\n }\n }, 200);\n }\n break;\n case \"counter\":\n if (selectedTechnique) {\n const p2CounterAnimName = resolveTechniqueAnimation(selectedTechnique);\n setPlayer2AttackAnimation(p2CounterAnimName);\n\n if (selectedTechnique.id) {\n setPlayer2TechniqueId(selectedTechnique.id);\n }\n const p2CounterAnim = getAnimation(p2CounterAnimName);\n const p2CounterDur = p2CounterAnim?.duration ?? 0.6;\n setPlayer2AttackDuration(p2CounterDur);\n player2Animation.transitionToAttack(p2CounterDur);\n } else {\n setPlayer2AttackAnimation(aiFallbackAnim);\n if (aiFallbackTechnique?.id) {\n setPlayer2TechniqueId(aiFallbackTechnique.id);\n }\n const p2FallbackAnim = getAnimation(aiFallbackAnim);\n const p2FallbackDur = p2FallbackAnim?.duration ?? 0.6;\n setPlayer2AttackDuration(p2FallbackDur);\n player2Animation.transitionToAttack(p2FallbackDur);\n }\n handleAIAttack(selectedTechnique, targetVitalPoint);\n addCombatMessage(\"AI 반격!\", \"AI Counter!\");\n break;\n }\n },\n [\n handleAIAttack,\n handleAIDefend,\n handleAITechnique,\n moveAIPlayer,\n addCombatMessage,\n validPlayers,\n arenaBounds,\n combatState.roundEnded,\n combatState.roundStarted,\n player2Animation,\n ],\n );\n\n useEffect(() => {\n executeAIActionCallbackRef.current = executeAIActionCallback;\n }, [executeAIActionCallback]);\n\n useEffect(() => {\n if (combatState.roundEnded && validPlayers.length === 2) {\n const player = validPlayers[0];\n const totalAttacks = (player.hitsLanded ?? 0) + (player.hitsTaken ?? 0);\n\n if (totalAttacks === 0) return;\n\n adaptiveDifficulty.updateSkillMetrics({\n hitsLanded: player.hitsLanded ?? 0,\n totalAttacks,\n combosExecuted: player.comboCount ?? 0,\n perfectBlockCount: 0,\n avgReactionTimeMs: 500,\n vitalPointsHit: player.vitalPointHits ?? 0,\n effectiveStanceChanges: 0,\n damageDealt: player.totalDamageDealt ?? 0,\n damageTaken: player.totalDamageReceived ?? 0,\n });\n }\n }, [combatState.roundEnded, adaptiveDifficulty, validPlayers]);\n\n const checkGameEnd = useCallback(() => {\n if (combatState.roundEnded) return;\n\n const p1Defeated = validPlayers[0].health <= 0;\n const p2Defeated = validPlayers[1].health <= 0;\n\n if (p1Defeated || p2Defeated) {\n combatActions.setRoundEnded(true);\n combatActions.setRoundStarted(false);\n combatActions.setRoundDisplayStatus(\"ko\");\n const winner = p1Defeated ? 1 : 0;\n const roundWinner = validPlayers[winner];\n\n updateMatchScore(winner);\n\n addCombatMessage(\n p1Defeated ? \"플레이어 1 패배\" : \"플레이어 1 승리!\",\n p1Defeated ? \"Player 1 Defeated\" : \"Player 1 Victory!\",\n );\n\n setTimeout(() => {\n startTransition(roundWinner, internalRound);\n }, 1500);\n }\n }, [\n validPlayers,\n addCombatMessage,\n combatState.roundEnded,\n combatActions,\n internalRound,\n startTransition,\n updateMatchScore,\n ]);\n\n useEffect(() => {\n checkGameEnd();\n }, [player1Health, player2Health, checkGameEnd]);\n\n useEffect(() => {\n const handleCombatInput = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") {\n event.preventDefault();\n if (showPauseMenu) {\n handleResume();\n } else {\n handlePause();\n }\n return;\n }\n\n if (isPaused || showPauseMenu) {\n return;\n }\n\n if (!matchCountdownComplete || showRoundStart) {\n return;\n }\n\n if (\n !combatState.roundStarted ||\n combatState.roundEnded ||\n combatState.isExecutingTechnique\n ) {\n return;\n }\n\n const key = event.key.toLowerCase();\n\n if (key >= \"1\" && key <= \"8\") {\n const stanceIndex = parseInt(key) - 1;\n const stances: TrigramStance[] = [\n TrigramStance.GEON,\n TrigramStance.TAE,\n TrigramStance.LI,\n TrigramStance.JIN,\n TrigramStance.SON,\n TrigramStance.GAM,\n TrigramStance.GAN,\n TrigramStance.GON,\n ];\n handleStanceSwitch(stances[stanceIndex]);\n event.preventDefault();\n }\n\n if (key === \" \") {\n handleAttackWithFeedback();\n event.preventDefault();\n }\n\n if (event.key === \"Shift\") {\n handleDefendWithFeedback();\n event.preventDefault();\n }\n\n if (event.key === \"f\" || event.key === \"F\") {\n handleStanceSideSwitch(0); // Human player\n event.preventDefault();\n }\n };\n\n window.addEventListener(\"keydown\", handleCombatInput);\n return () => window.removeEventListener(\"keydown\", handleCombatInput);\n }, [\n combatState.roundStarted,\n combatState.roundEnded,\n combatState.isExecutingTechnique,\n matchCountdownComplete,\n showRoundStart,\n isPaused,\n showPauseMenu,\n handleStanceSwitch,\n handleStanceSideSwitch,\n handleAttackWithFeedback,\n handleDefendWithFeedback,\n handlePause,\n handleResume,\n ]);\n\n const player1MovementState = useMemo(() => {\n if (!validPlayers[0]?.bodyPartHealth) {\n return {\n statusText: { korean: \"정상\", english: \"Normal\" },\n isLimping: false,\n isSevereLimp: false,\n };\n }\n\n const result = injuryMovementModifier.calculateMovementSpeed(\n 1.0,\n validPlayers[0].bodyPartHealth,\n validPlayers[0].currentStance ?? TrigramStance.GEON,\n validPlayers[0].pain ?? 0,\n );\n\n return {\n statusText: result.statusText,\n isLimping: result.isLimping,\n isSevereLimp: result.isSevereLimp,\n speedMultiplier: result.speedMultiplier,\n };\n }, [validPlayers]);\n\n const player2MovementState = useMemo(() => {\n if (!validPlayers[1]?.bodyPartHealth) {\n return {\n statusText: { korean: \"정상\", english: \"Normal\" },\n isLimping: false,\n isSevereLimp: false,\n };\n }\n\n const result = injuryMovementModifier.calculateMovementSpeed(\n 1.0,\n validPlayers[1].bodyPartHealth,\n validPlayers[1].currentStance ?? TrigramStance.GEON,\n validPlayers[1].pain ?? 0,\n );\n\n return {\n statusText: result.statusText,\n isLimping: result.isLimping,\n isSevereLimp: result.isSevereLimp,\n speedMultiplier: result.speedMultiplier,\n };\n }, [validPlayers]);\n\n return (\n <div\n style={{\n width: `${width}px`,\n height: `${height}px`,\n position: \"relative\",\n backgroundColor: toHexColor(KOREAN_COLORS.UI_BACKGROUND_DARK),\n overflow: \"hidden\", // Prevent content from extending beyond container\n }}\n data-testid=\"combat-screen\"\n >\n {/* Three.js Canvas for 3D rendering */}\n <Canvas\n style={{ width: `${width}px`, height: `${height}px` }}\n camera={{\n position: cameraConfig.position,\n fov: cameraConfig.fov,\n near: cameraConfig.near,\n far: cameraConfig.far,\n }}\n gl={{\n antialias: renderConfig.antialias,\n alpha: false,\n powerPreference: \"high-performance\",\n failIfMajorPerformanceCaveat: false,\n }}\n dpr={renderConfig.dpr}\n shadows={false} // Temporarily disable shadows\n onCreated={({ gl }) => {\n gl.setClearColor(theme.colors.UI_BACKGROUND_DARK, 1);\n }}\n >\n {/* Lighting - CombatArena3D provides ambient, we add directional for shadows */}\n <ambientLight intensity={0.6} />\n <directionalLight position={[10, 10, 5]} intensity={1.2} />\n\n {/* Adaptive Quality Wrapper monitors FPS and adjusts quality */}\n <AdaptiveQualityWrapper\n enabled={shouldEnableAdaptiveQuality}\n isMobile={isMobile}\n >\n {/* Performance overlay (dev mode) - controlled by showPerformanceOverlay prop */}\n {showPerformanceOverlay && !isMobile && !showPerformanceMonitor && (\n <PerformanceOverlay3D />\n )}\n\n {/* Combat Arena 3D Environment - uses physics-based world dimensions */}\n <CombatArena3D\n lighting=\"cyberpunk\"\n scale={arenaBounds.scale}\n worldWidthMeters={arenaBounds.worldWidthMeters}\n worldDepthMeters={arenaBounds.worldDepthMeters}\n />\n\n {/* Animation updater - updates both player animations at 60fps */}\n <AnimationUpdater\n player1Animation={player1Animation}\n player2Animation={player2Animation}\n />\n\n {/* Acceleration updater - tracks player 1 movement time and updates speed */}\n <AccelerationUpdater\n isMoving={player1IsMoving}\n velocity={player1Velocity}\n movementTimeRef={player1MovementTimeRef}\n lastDirectionRef={player1LastDirectionRef}\n onSpeedUpdate={setPlayer1AccelerationBasedSpeed}\n walkSpeed={player1WalkRunSpeeds.walkSpeed}\n runSpeed={player1WalkRunSpeeds.runSpeed}\n />\n\n {/* Player 1 (Human) */}\n <Player3DWithTransitions\n {...convertPlayerStateToProps(\n validPlayers[0],\n player1PositionWithAttackMovement,\n player1Rotation,\n {\n isMobile,\n facing: \"right\",\n enableFacialExpressions: true,\n enableEyeTracking: true,\n opponentPosition: player2PositionWithAttackMovement,\n },\n )}\n currentAnimation={animationStateToPlayerAnimation(\n player1Animation.currentState,\n )}\n attackAnimation={player1AttackAnimation}\n laterality={combatState.playerLaterality[0]}\n enableTransitionEffects={!isMobile}\n enableStanceSymbol={!isMobile}\n enableStanceAudio={true}\n />\n\n {/* Player 2 (AI) */}\n <Player3DWithTransitions\n {...convertPlayerStateToProps(\n validPlayers[1],\n player2PositionWithAttackMovement,\n player2Rotation,\n {\n isMobile,\n facing: \"right\",\n enableFacialExpressions: true,\n enableEyeTracking: true,\n opponentPosition: player1PositionWithAttackMovement,\n },\n )}\n currentAnimation={animationStateToPlayerAnimation(\n player2Animation.currentState,\n )}\n attackAnimation={player2AttackAnimation}\n laterality={combatState.playerLaterality[1]}\n enableTransitionEffects={!isMobile}\n enableStanceSymbol={!isMobile}\n enableStanceAudio={true}\n />\n\n {/* Movement Status Indicators - Korean/English Bilingual */}\n {/* Player 1 Movement Status */}\n {(player1MovementState.isLimping ||\n player1MovementState.isSevereLimp) && (\n <Html\n position={[\n player1Position3D[0],\n player1Position3D[1] + 2.5,\n player1Position3D[2],\n ]}\n center\n data-testid=\"player1-movement-status\"\n >\n <div\n style={{\n fontSize: isMobile ? \"12px\" : \"14px\",\n color: player1MovementState.isSevereLimp\n ? toHexColor(KOREAN_COLORS.TEXT_ERROR)\n : toHexColor(KOREAN_COLORS.ACCENT_GOLD),\n fontFamily: FONT_FAMILY.KOREAN,\n fontWeight: \"bold\",\n textShadow: \"0 0 4px rgba(0,0,0,0.8)\",\n background: \"rgba(0, 0, 0, 0.6)\",\n padding: \"4px 8px\",\n borderRadius: \"4px\",\n whiteSpace: \"nowrap\",\n }}\n >\n {player1MovementState.statusText.korean} |{\" \"}\n {player1MovementState.statusText.english}\n </div>\n </Html>\n )}\n\n {/* Player 2 Movement Status */}\n {(player2MovementState.isLimping ||\n player2MovementState.isSevereLimp) && (\n <Html\n position={[\n player2Position3D[0],\n player2Position3D[1] + 2.5,\n player2Position3D[2],\n ]}\n center\n data-testid=\"player2-movement-status\"\n >\n <div\n style={{\n fontSize: isMobile ? \"12px\" : \"14px\",\n color: player2MovementState.isSevereLimp\n ? toHexColor(KOREAN_COLORS.TEXT_ERROR)\n : toHexColor(KOREAN_COLORS.ACCENT_GOLD),\n fontFamily: FONT_FAMILY.KOREAN,\n fontWeight: \"bold\",\n textShadow: \"0 0 4px rgba(0,0,0,0.8)\",\n background: \"rgba(0, 0, 0, 0.6)\",\n padding: \"4px 8px\",\n borderRadius: \"4px\",\n whiteSpace: \"nowrap\",\n }}\n >\n {player2MovementState.statusText.korean} |{\" \"}\n {player2MovementState.statusText.english}\n </div>\n </Html>\n )}\n\n {/* Trauma Overlays - Injury Visualization (외상 오버레이 - 부상 시각화) */}\n {/* Player 1 Injuries */}\n <TraumaOverlay3D\n playerId=\"player\"\n health={validPlayers[0].health}\n injuries={player1Injuries}\n characterPosition={player1Position3D}\n isMobile={isMobile}\n showFractures={true}\n />\n\n {/* Player 2 Injuries */}\n <TraumaOverlay3D\n playerId=\"enemy\"\n health={validPlayers[1].health}\n injuries={player2Injuries}\n characterPosition={player2Position3D}\n isMobile={isMobile}\n showFractures={true}\n />\n\n {/* Hit Effects */}\n <HitEffects3D\n effects={combatState.hitEffects}\n onEffectComplete={handleEffectComplete}\n arenaBounds={arenaBounds}\n />\n\n {/* Combat Particle Effects - Blood viscosity, organ damage, audio (전투 입자 효과) */}\n <CombatParticleEffects3D\n hitEffects={combatState.hitEffects}\n enabled={true}\n isMobile={isMobile}\n />\n\n {/* Vital Point Overlay - Show on both players when V is pressed */}\n {overlayVisible && (\n <>\n {/* Player 1 Vital Points */}\n <VitalPointMarkers3D\n position={player1Position3D}\n visible={overlayVisible}\n severityFilter={severityFilters}\n regionFilter={regionFilter}\n searchQuery={searchQuery}\n showLabels={showLabels}\n scale={scale}\n animated={animated}\n onPointClick={() => {\n }}\n />\n\n {/* Player 2 Vital Points */}\n <VitalPointMarkers3D\n position={player2Position3D}\n visible={overlayVisible}\n severityFilter={severityFilters}\n regionFilter={regionFilter}\n searchQuery={searchQuery}\n showLabels={showLabels}\n scale={scale}\n animated={animated}\n onPointClick={() => {\n }}\n />\n\n {/* Vital Point Overlay Controls - only visible when overlay is active */}\n <VitalPointOverlayControlsHtml\n screenPosition={{\n top: `${layoutConstants.hudHeight + layoutConstants.padding}px`,\n left: `${layoutConstants.padding}px`,\n }}\n visible={overlayVisible}\n onVisibleChange={setOverlayVisible}\n severityFilters={severityFilters}\n onSeverityFiltersChange={setSeverityFilters}\n regionFilter={regionFilter}\n onRegionFilterChange={setRegionFilter}\n searchQuery={searchQuery}\n onSearchQueryChange={setSearchQuery}\n showLabels={showLabels}\n onShowLabelsChange={setShowLabels}\n animated={animated}\n onAnimatedChange={setAnimated}\n scale={scale}\n onScaleChange={setScale}\n isMobile={isMobile}\n />\n </>\n )}\n\n {/* Action Feedback - Damage Numbers */}\n <DamageNumbers\n damages={feedbackState.damageNumbers}\n isMobile={isMobile}\n arenaBounds={arenaBounds}\n />\n\n {/* Action Feedback - Action Indicators */}\n <ActionFeedback\n feedbacks={feedbackState.actionFeedbacks}\n isMobile={isMobile}\n arenaBounds={arenaBounds}\n />\n\n {/* Combo Counter */}\n <ComboCounter combo={feedbackState.comboCount} isMobile={isMobile} />\n\n {/* Technique Name Display */}\n {feedbackState.currentTechnique && (\n <TechniqueName\n korean={feedbackState.currentTechnique.korean}\n english={feedbackState.currentTechnique.english}\n isMobile={isMobile}\n onComplete={() => feedbackActions.hideTechnique()}\n />\n )}\n\n {/* Performance Overlay (Development Only) - Toggle with P key */}\n {import.meta.env.DEV && showPerformanceMonitor && (\n <PerformanceOverlay3D visible={true} />\n )}\n\n {/* Visual Feedback Components for Keyboard Controls */}\n <StanceChangeIndicator\n currentStance={currentStanceIndex}\n previousStance={previousStance}\n isMobile={isMobile}\n />\n\n <KeyboardHints\n visible={showHints}\n currentStance={currentStanceIndex}\n isMobile={isMobile}\n />\n\n <InputBufferDisplay queuedInputs={queuedInputs} isMobile={isMobile} />\n\n {/* 3D Balance Indicators - Positioned below top HUD, to the right of side HUDs */}\n {/* Player 1 Balance Indicator - Upper left area, below top HUD */}\n {validPlayers[0] && (\n <BalanceIndicatorOverlayHtml\n player={validPlayers[0] as BalancePlayerState}\n currentTime={currentTime}\n position={[\n -2.5, // Left side of arena (to the right of left HUD in 3D space)\n 2.5, // Upper area (below top HUD)\n -1.0, // Slightly forward toward camera\n ]}\n isMobile={isMobile}\n />\n )}\n\n {/* Player 2 Balance Indicator - Upper right area, below top HUD */}\n {validPlayers[1] && (\n <BalanceIndicatorOverlayHtml\n player={validPlayers[1] as BalancePlayerState}\n currentTime={currentTime}\n position={[\n 2.5, // Right side of arena (to the left of right HUD in 3D space)\n 2.5, // Upper area (below top HUD)\n -1.0, // Slightly forward toward camera\n ]}\n isMobile={isMobile}\n />\n )}\n\n {/* Mobile Touch Controls moved outside Canvas - using MobileControlsOverlay for reliable touch events */}\n\n {/* Performance Monitoring - FPS display (dev mode, toggle with P key) */}\n {process.env.NODE_ENV === \"development\" && showPerformanceMonitor && (\n <FPSMonitor\n enabled={true}\n warningThreshold={50}\n criticalThreshold={30}\n />\n )}\n </AdaptiveQualityWrapper>\n\n {/* Post-processing Effects - desktop high tier only for Android WebGL stability */}\n {renderConfig.postProcessing && (\n <EffectComposer multisampling={4}>\n <Bloom\n luminanceThreshold={0.9}\n luminanceSmoothing={0.9}\n mipmapBlur\n intensity={0.8}\n radius={0.4}\n />\n <Noise opacity={0.03} />\n <Vignette eskil={false} offset={0.1} darkness={0.3} />\n </EffectComposer>\n )}\n </Canvas>\n\n {/* Html UI Overlays (positioned absolutely over Canvas) */}\n <div\n style={{\n position: \"absolute\",\n top: 0,\n left: 0,\n width: \"100%\",\n height: \"100%\",\n pointerEvents: \"none\",\n zIndex: Z_INDEX.HUD,\n overflow: \"clip\",\n }}\n >\n {/* Top HUD - Round info, timer, return to menu */}\n <CombatTopHUD\n width={width}\n height={height}\n isMobile={isMobile}\n positionScale={positionScale}\n currentRound={internalRound}\n totalRounds={3}\n timerState={timerState}\n showTimer={\n combatState.roundStarted &&\n !combatState.roundEnded &&\n matchCountdownComplete &&\n !showRoundStart\n }\n onReturnToMenu={onReturnToMenu}\n isPaused={isPaused || showPauseMenu}\n />\n\n {/* Left HUD - Player 1 stats.\n On mobile, side HUDs occlude the 3D arena in both portrait and\n landscape; collapse them away so the arena stays fully visible.\n Player status remains available via CombatPortraitStatusStrip and\n bottom combat controls. */}\n {!isMobile && (\n <CombatLeftHUD\n width={width}\n height={height}\n isMobile={isMobile}\n positionScale={positionScale}\n player={validPlayers[0]}\n laterality={combatState.playerLaterality[0]}\n isInGuard={player1Animation.isInStanceGuard()}\n speedModifiers={player1SpeedModifiers}\n />\n )}\n\n {/* Right HUD - Player 2/AI stats with difficulty indicator */}\n {!isMobile && (\n <CombatRightHUD\n width={width}\n height={height}\n isMobile={isMobile}\n positionScale={positionScale}\n player={validPlayers[1]}\n laterality={combatState.playerLaterality[1]}\n speedModifiers={player2SpeedModifiers}\n difficultyTier={currentDifficultyTier}\n />\n )}\n\n {/* Portrait-mobile HP/stamina strip. Replaces the hidden side HUDs\n so both players can still see their health at a glance without\n re-introducing arena occlusion. */}\n {isMobile && isPortrait && (\n <CombatPortraitStatusStrip\n width={width}\n height={height}\n player1={validPlayers[0]}\n player2={validPlayers[1]}\n positionScale={positionScale}\n topOffset={layoutConstants.hudHeight}\n />\n )}\n\n {/* Bottom HUD - Technique bar, volume, messages */}\n <CombatBottomHUD\n width={width}\n height={height}\n isMobile={isMobile}\n positionScale={positionScale}\n visible={\n combatState.roundStarted &&\n !combatState.roundEnded &&\n matchCountdownComplete &&\n !showRoundStart\n }\n techniques={techniqueSelection.availableTechniques}\n player={validPlayers[0]}\n selectedIndex={techniqueSelection.selectedIndex}\n cooldowns={cooldownsMap}\n onTechniqueSelect={techniqueSelection.selectTechnique}\n combatMessages={combatState.combatMessages}\n />\n\n {/* Player State Visual Indicators */}\n {/* Player 1 State Overlay - includes consciousness blur, pain vignette, etc.\n In portrait mobile the arena is already rendered in a compressed 3:4\n aspect ratio, so halve the fullscreen vignette/blur/flash intensity\n to avoid further obscuring the scene. */}\n <PlayerStateOverlayHtml\n pain={validPlayers[0].pain}\n balanceState={getBalanceState(validPlayers[0].balance)}\n position=\"left\"\n consciousness={validPlayers[0].consciousness}\n bloodLoss={0} // FIXME: bloodLoss property not yet added to PlayerState interface - overlay will not display until implemented\n stamina={validPlayers[0].stamina}\n isMobile={isMobile}\n intensityScale={isMobile && isPortrait ? 0.5 : 1}\n />\n\n {/* Note: Player 2 (AI) does not get fullscreen state overlays like consciousness blur */}\n {/* as those effects would incorrectly affect the player's view */}\n\n {/* Breathing Disruption Indicators */}\n {/* Player 1 Breathing Indicator - positioned near left HUD */}\n <div\n style={{\n position: \"absolute\",\n left: isMobile ? \"10px\" : \"20px\",\n top: isMobile ? \"120px\" : \"160px\",\n zIndex: Z_INDEX.HUD + 1,\n pointerEvents: \"none\",\n }}\n data-testid=\"player1-breathing-indicator-container\"\n >\n <BreathingIndicator player={validPlayers[0]} isMobile={isMobile} />\n </div>\n\n {/* Player 2 Breathing Indicator - positioned near right HUD */}\n <div\n style={{\n position: \"absolute\",\n right: isMobile ? \"10px\" : \"20px\",\n top: isMobile ? \"120px\" : \"160px\",\n zIndex: Z_INDEX.HUD + 1,\n pointerEvents: \"none\",\n }}\n data-testid=\"player2-breathing-indicator-container\"\n >\n <BreathingIndicator player={validPlayers[1]} isMobile={isMobile} />\n </div>\n\n {/* Pause Menu Overlay */}\n {(isPaused || showPauseMenu) && (\n <PauseMenu\n onResume={handleResume}\n onRestart={handleRestart}\n onReturnToMenu={onReturnToMenu}\n isMobile={isMobile}\n />\n )}\n </div>\n\n {/* Round Announcement Overlay */}\n {showAnnouncement && roundWinner && (\n <RoundAnnouncement\n roundNumber={transitionRoundNumber}\n roundWinner={roundWinner}\n currentScore={matchScore}\n roundStats={{\n damageDealt: roundWinner.totalDamageDealt ?? 0,\n hitsLanded: roundWinner.hitsLanded ?? 0,\n vitalPointsHit: roundWinner.vitalPointHits ?? 0,\n accuracy: calculateAccuracy(roundWinner),\n }}\n onCountdownComplete={() => {\n if (matchScore.player1 >= 2 || matchScore.player2 >= 2) {\n const winner = matchScore.player1 >= 2 ? 0 : 1;\n onGameEnd(winner);\n } else {\n skipCountdown();\n }\n }}\n onSkip={() => {\n if (matchScore.player1 >= 2 || matchScore.player2 >= 2) {\n const winner = matchScore.player1 >= 2 ? 0 : 1;\n onGameEnd(winner);\n } else {\n skipCountdown();\n }\n }}\n isMobile={isMobile}\n totalRounds={3}\n />\n )}\n\n {/* Match Start Countdown Overlay - only shows once at match start */}\n {showMatchCountdown && !hasShownMatchCountdown && (\n <MatchCountdown\n onComplete={() => {\n setHasShownMatchCountdown(true);\n setShowMatchCountdown(false);\n setMatchCountdownComplete(true);\n startRound();\n }}\n isMobile={isMobile}\n showSkip={false}\n />\n )}\n\n {/* Round Start Announcement for subsequent rounds */}\n {/* Note: showRoundStart is only set to true after round 1 ends, so no need for internalRound > 1 check */}\n {showRoundStart && (\n <RoundStartAnnouncement\n roundNumber={internalRound}\n duration={2}\n onComplete={() => {\n if (import.meta.env.DEV) {\n console.log(\n \"[DEV] Round start announcement complete for round\",\n internalRound,\n );\n }\n setShowRoundStart(false);\n startRound();\n }}\n isMobile={isMobile}\n />\n )}\n\n {/* Round Display Status - Brief status messages */}\n {contentReady && combatState.roundDisplayStatus && (\n <RoundDisplayStatus\n status={combatState.roundDisplayStatus}\n isMobile={isMobile}\n />\n )}\n\n {/* Mobile Controls - Pure DOM, rendered OUTSIDE Canvas for reliable touch events */}\n {/* Uses pure DOM handlers instead of drei's Html which can block touch events on mobile */}\n {isMobile && (\n <>\n <MobileControlsOverlay\n onMove={handleMobileMove}\n onAttack={handleMobileAttack}\n onBlock={handleMobileBlock}\n bottom={getMobileControlsBottom(height)}\n viewportWidth={width}\n viewportHeight={height}\n />\n\n <StanceWheelPure\n currentStance={currentStanceIndex}\n onStanceChange={handleMobileStanceChange}\n expanded={stanceWheelExpanded}\n onToggle={toggleStanceWheel}\n disabled={!mobileControlsEnabled}\n opacity={0.8}\n />\n\n <GestureRecognizerPure\n onGesture={handleMobileGesture}\n enabled={mobileControlsEnabled}\n showFeedback={true}\n minSwipeDistance={50}\n />\n </>\n )}\n </div>\n );\n};\n\nexport default CombatScreen3D;\n"],"mappings":"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"}
1
+ {"version":3,"file":"CombatScreen3D.js","names":[],"sources":["../../../../src/components/screens/combat/CombatScreen3D.tsx"],"sourcesContent":["/**\n * CombatScreen3D - Three.js-based combat screen (Black Trigram 흑괘)\n *\n * Maintains all existing combat logic and state management\n * Uses Html overlays for UI and 3D meshes for game objects\n */\n\nimport { Canvas } from \"@react-three/fiber\";\nimport { Html } from \"@react-three/drei\";\nimport {\n Bloom,\n EffectComposer,\n Noise,\n Vignette,\n} from \"@react-three/postprocessing\";\nimport React, {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { useAudio } from \"../../../audio/AudioProvider\";\nimport { useActionFeedback } from \"../../../hooks/useActionFeedback\";\nimport { useCombatTimer } from \"../../../hooks/useCombatTimer\";\nimport { useKeyboardControls } from \"../../../hooks/useKeyboardControls\";\nimport { usePlayerAnimation } from \"../../../hooks/usePlayerAnimation\";\nimport { useRoundTransition } from \"../../../hooks/useRoundTransition\";\nimport { useTechniqueSelection } from \"../../../hooks/useTechniqueSelection\";\nimport { useWebGLContextLossHandler } from \"../../../hooks/useWebGLContextLossHandler\";\nimport { useCombatAttackMovement } from \"./hooks/useCombatAttackMovement\";\nimport { HitEffect, PlayerState } from \"../../../systems\";\nimport { CombatSystem } from \"../../../systems/CombatSystem\";\nimport {\n AdaptiveDifficulty,\n getPersonalityByArchetype,\n} from \"../../../systems/ai\";\nimport {\n AnimationEvents,\n AnimationState,\n AnimationType,\n determineRecoveryType,\n getAnimation,\n getAnimationDurationOrFallback,\n getRecoveryAnimationState,\n resolveTechniqueAnimation,\n TARGET_ANIMATION_FPS,\n} from \"../../../systems/animation\";\nimport { BalanceSystem } from \"../../../systems/combat/BalanceSystem\";\nimport type { BalancePlayerState } from \"../../../systems/combat/BalanceSystem\";\nimport { HitEffectType } from \"../../../systems/effects\";\nimport { injuryMovementModifier } from \"../../../systems/movement/InjuryMovementModifier\";\nimport { TRIGRAM_STANCES_ORDER } from \"../../../systems/trigram/types\";\nimport { TRIGRAM_TECHNIQUES } from \"../../../systems/trigram/techniques\";\nimport type { KoreanTechnique } from \"../../../systems/vitalpoint/types\";\nimport {\n CombatState,\n GameMode,\n PlayerArchetype,\n Position,\n TrigramStance,\n} from \"../../../types\";\nimport { Injury, InjuryType } from \"../../../types/injury\";\nimport { Z_INDEX } from \"../../../types/LayoutTypes\";\nimport {\n COMBAT_TOP_HUD_HEIGHT_PERCENT,\n getMobileControlsBottom,\n} from \"../../../types/constants/layout\";\nimport {\n FONT_FAMILY,\n getPerformanceSettings,\n KOREAN_COLORS,\n ROUND_ANNOUNCEMENT_TIMINGS,\n} from \"@/types/constants\";\nimport { getAnimationTypeForTechnique } from \"../../../data/techniqueMappings\";\nimport { toHexColor } from \"../../../utils/colorHelpers\";\nimport { usePlayerMovement } from \"../../../utils/inputSystem\";\nimport { PerformanceOverlay3D } from \"../../../utils/performance\";\nimport { getHUDHeight } from \"../../../utils/responsiveLayout\";\nimport { getHUDPositionScale } from \"../../../utils/responsiveLayoutHelpers\";\nimport { createPlayerFromArchetype } from \"../../../utils/playerUtils\";\nimport { createCameraConfig } from \"../../../utils/sharedPhysicsConfig\";\nimport { useAdaptiveQuality } from \"../../shared/three/optimization\";\nimport { useKoreanTheme } from \"../../shared/base/useKoreanTheme\";\nimport {\n ActionFeedback,\n TechniqueName,\n} from \"../../shared/three/effects/ActionFeedback\";\nimport { DamageNumbers } from \"../../shared/three/effects/DamageNumbers\";\nimport HitEffects3D from \"../../shared/three/effects/HitEffects3D\";\nimport { VitalPointMarkers3D } from \"../../shared/three/effects/VitalPointMarkers3D\";\nimport { StanceChangeIndicator } from \"../../shared/three/indicators/StanceChangeIndicator\";\nimport { CombatArena3D } from \"../../shared/three/scene/CombatArena3D\";\nimport { BreathingIndicator } from \"../../shared/three/ui/BreathingIndicator\";\nimport { ComboCounter } from \"../../shared/three/ui/ComboCounter\";\nimport { VitalPointOverlayControlsHtml } from \"../../shared/three/ui/VitalPointOverlayControlsHtml\";\nimport { KeyboardHints } from \"./components/controls/KeyboardHints\";\nimport { MatchCountdown } from \"./components/feedback/MatchCountdown\";\nimport { RoundAnnouncement } from \"./components/feedback/RoundAnnouncementOverlayHtml\";\nimport { RoundDisplayStatus } from \"./components/feedback/RoundDisplayStatus\";\nimport { RoundStartAnnouncement } from \"./components/feedback/RoundStartAnnouncementOverlayHtml\";\nimport { InputBufferDisplay } from \"./components/indicators/InputBufferDisplay\";\nimport { GestureEvent } from \"../../../hooks/useTouchControls\";\nimport {\n MovementType,\n SpeedModifierSystem,\n} from \"../../../systems/physics/SpeedModifierSystem\";\nimport { Technique } from \"../../../types\";\nimport {\n animationStateToPlayerAnimation,\n convertPlayerStateToProps,\n getBalanceState,\n} from \"../../../utils/player3DHelpers\";\nimport {\n GestureRecognizerPure,\n MobileControlsOverlay,\n StanceWheelPure,\n} from \"../../shared/mobile\";\nimport { ButtonEventType } from \"../../shared/mobile/ActionButtons\";\nimport { Direction, DPadEventType } from \"../../shared/mobile/VirtualDPad\";\nimport { Player3DWithTransitions } from \"../../shared/three/models/Player3DWithTransitions\";\nimport { PauseMenu } from \"./components/controls/PauseMenu\";\nimport { TraumaOverlay3D } from \"./components/effects/TraumaOverlay3D\";\nimport { CombatParticleEffects3D } from \"./components/effects/CombatParticleEffects3D\";\nimport {\n CombatBottomHUD,\n CombatLeftHUD,\n CombatPortraitStatusStrip,\n CombatRightHUD,\n CombatTopHUD,\n} from \"./components/hud\";\nimport { FPSMonitor } from \"./components/hud/FPSMonitor\";\nimport { PlayerStateOverlayHtml } from \"./components/hud/PlayerStateOverlayHtml\";\nimport { BalanceIndicatorOverlayHtml } from \"../../ui/combat/BalanceIndicatorOverlayHtml\";\nimport {\n ANNOUNCEMENT_FADE_OUT_DELAY,\n calculateAccuracy,\n STANCE_INDEX_MAP,\n} from \"./helpers\";\nimport { AnimationUpdater } from \"./helpers/AnimationUpdater\";\nimport { AccelerationUpdater } from \"../../../systems/movement/helpers/AccelerationUpdater\";\nimport { isRunningSpeed } from \"../../../systems/movement/helpers/accelerationUtils\";\nimport { useAICombat } from \"./hooks/useAICombat\";\nimport { useCombatActions } from \"./hooks/useCombatActions\";\nimport { useCombatAudio } from \"./hooks/useCombatAudio\";\nimport { useCombatLayout } from \"./hooks/useCombatLayout\";\nimport { useCombatState } from \"./hooks/useCombatState\";\n\nconst PLAYER_ONE_INDEX = 0;\n\n/**\n * Props for the CombatScreen3D component.\n * Provides all state and callbacks required for the 3D combat screen.\n */\nexport interface CombatScreen3DProps {\n /**\n * Array of player states (expects exactly 2 players).\n * Each PlayerState contains all combat and status information for a player.\n */\n readonly players: readonly PlayerState[];\n /**\n * Callback to update a player's state by index.\n * @param playerIndex - Index of the player to update (0 or 1).\n * @param updates - Partial PlayerState with updated fields.\n */\n readonly onPlayerUpdate: (\n playerIndex: number,\n updates: Partial<PlayerState>,\n ) => void;\n /**\n * Current round number (1-based).\n */\n readonly currentRound: number;\n /**\n * Remaining time in seconds for the current round.\n */\n readonly timeRemaining: number;\n /**\n * Whether combat is currently paused.\n */\n readonly isPaused: boolean;\n /**\n * Callback when the user exits to the menu.\n */\n readonly onReturnToMenu: () => void;\n /**\n * Callback when the match ends, with the winner's index (0 or 1).\n * @param winner - Index of the winning player.\n */\n readonly onGameEnd: (winner: number) => void;\n /**\n * Optional game mode (affects rules/behavior).\n */\n readonly gameMode?: GameMode;\n /**\n * Canvas width in pixels. Defaults to 1200.\n */\n readonly width?: number;\n /**\n * Canvas height in pixels. Defaults to 800.\n */\n readonly height?: number;\n /**\n * Enable adaptive quality adjustment (default: true on mobile)\n */\n readonly enableAdaptiveQuality?: boolean;\n /**\n * Show performance overlay in dev mode (default: import.meta.env.DEV)\n */\n readonly showPerformanceOverlay?: boolean;\n}\n\n/**\n * CombatScreen3D Component\n * Three.js-based combat screen with 3D characters and effects\n */\n\n/**\n * AdaptiveQualityWrapper - Internal component to use adaptive quality hook\n * Must be inside Canvas to use useFrame from @react-three/fiber\n *\n * Hoisted outside CombatScreen3D to avoid \"Cannot create components during render\"\n * warnings from react-hooks/component-creation. Keeps the component type stable\n * across renders of the parent.\n */\nconst AdaptiveQualityWrapper: React.FC<{\n readonly enabled: boolean;\n readonly isMobile: boolean;\n readonly children: React.ReactNode;\n}> = ({ enabled, isMobile, children }) => {\n useAdaptiveQuality(enabled, isMobile, (newQuality) => {\n if (import.meta.env.DEV) {\n console.log(`[CombatScreen3D] Quality adjusted to: ${newQuality}`);\n }\n });\n\n return <>{children}</>;\n};\n\nexport const CombatScreen3D: React.FC<CombatScreen3DProps> = ({\n players,\n onPlayerUpdate,\n currentRound,\n timeRemaining,\n isPaused,\n onReturnToMenu,\n onGameEnd,\n width = 1200,\n height = 800,\n enableAdaptiveQuality,\n showPerformanceOverlay = import.meta.env.DEV,\n}) => {\n const [contentReady, setContentReady] = useState(false);\n\n const contextLossCountRef = useRef(0);\n\n useWebGLContextLossHandler({\n onContextLost: () => {\n console.warn(\"⚠️ WebGL context lost in CombatScreen\");\n contextLossCountRef.current += 1;\n setContentReady(false);\n },\n onContextRestored: () => {\n setTimeout(() => setContentReady(true), 100);\n },\n autoRestore: true,\n });\n\n useEffect(() => {\n const timer = setTimeout(() => setContentReady(true), 50);\n return () => clearTimeout(timer);\n }, []);\n\n const audio = useAudio();\n\n useEffect(() => {\n if (import.meta.env.DEV) {\n performance.mark(\"combat-3d-render-start\");\n return () => {\n performance.mark(\"combat-3d-render-end\");\n performance.measure(\n \"combat-3d-render\",\n \"combat-3d-render-start\",\n \"combat-3d-render-end\",\n );\n };\n }\n }, []);\n\n const { arenaBounds, isMobile, isPortrait, screenSize, layoutConstants } =\n useCombatLayout(width, height);\n\n const theme = useKoreanTheme({\n variant: \"primary\",\n size: \"md\",\n isMobile,\n });\n\n const positionScale = useMemo(\n () => getHUDPositionScale(screenSize, isMobile),\n [screenSize, isMobile],\n );\n\n const combatTopHudHeight = useMemo(\n () => getHUDHeight(height, COMBAT_TOP_HUD_HEIGHT_PERCENT) * positionScale,\n [height, positionScale],\n );\n\n const cameraConfig = useMemo(() => {\n const base = createCameraConfig(isMobile);\n if (!isPortrait) return base;\n return {\n ...base,\n fov: Math.min(80, base.fov + 15),\n position: [base.position[0], base.position[1], base.position[2] + 4] as [\n number,\n number,\n number,\n ],\n };\n }, [isMobile, isPortrait]);\n\n const renderConfig = useMemo(() => {\n const performanceSettings = getPerformanceSettings(width, isMobile);\n\n return {\n shadowMapSize: performanceSettings.shadowMapSize,\n dpr: performanceSettings.dpr,\n antialias: performanceSettings.antialias,\n maxParticles: performanceSettings.maxParticles,\n postProcessing: performanceSettings.postProcessing,\n };\n }, [isMobile, width]);\n\n const shouldEnableAdaptiveQuality = enableAdaptiveQuality ?? isMobile;\n\n const { state: combatState, actions: combatActions } = useCombatState();\n\n\n const [overlayVisible, setOverlayVisible] = useState(false);\n const [severityFilters, setSeverityFilters] = useState<\n import(\"../../../types/common\").VitalPointSeverity[]\n >([]);\n const [regionFilter, setRegionFilter] =\n useState<\n import(\"../../shared/three/ui/VitalPointOverlayControlsHtml\").BodyRegionFilter\n >(\"all\");\n const [searchQuery, setSearchQuery] = useState(\"\");\n const [showLabels, setShowLabels] = useState(true);\n const [animated, setAnimated] = useState(true);\n const [scale, setScale] = useState(1.2); // Larger scale for better visibility in combat\n const [showPerformanceMonitor, setShowPerformanceMonitor] = useState(false);\n\n useEffect(() => {\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === \"v\" || e.key === \"V\") {\n setOverlayVisible((prev) => !prev);\n audio.playSFX(\"menu_select\");\n }\n if (e.key === \"F9\" && import.meta.env.DEV) {\n e.preventDefault();\n setShowPerformanceMonitor((prev) => !prev);\n }\n };\n\n window.addEventListener(\"keydown\", handleKeyDown);\n return () => {\n window.removeEventListener(\"keydown\", handleKeyDown);\n };\n }, [audio]);\n\n const { state: feedbackState, actions: feedbackActions } = useActionFeedback({\n damageNumberDuration: 1500,\n actionFeedbackDuration: 1200,\n techniqueDuration: 2000,\n comboResetTime: 2000,\n });\n\n const combatAudio = useCombatAudio();\n const { playStanceChangeSound } = combatAudio;\n\n const [matchScore, setMatchScore] = useState({ player1: 0, player2: 0 });\n const matchScoreRef = useRef(matchScore);\n\n const updateMatchScore = useCallback((winner: 0 | 1) => {\n const newScore = {\n player1:\n winner === 0\n ? matchScoreRef.current.player1 + 1\n : matchScoreRef.current.player1,\n player2:\n winner === 1\n ? matchScoreRef.current.player2 + 1\n : matchScoreRef.current.player2,\n };\n matchScoreRef.current = newScore;\n setTimeout(() => setMatchScore(newScore), 0);\n }, []);\n\n const [internalRound, setInternalRound] = useState(currentRound);\n\n const [currentTime, setCurrentTime] = useState(() => Date.now());\n\n const [hasShownMatchCountdown, setHasShownMatchCountdown] = useState(true); // Already shown (skipped)\n const [showMatchCountdown, setShowMatchCountdown] = useState(false); // Don't show\n const [showRoundStart, setShowRoundStart] = useState(false);\n const [matchCountdownComplete, setMatchCountdownComplete] = useState(true); // Already complete (skipped)\n\n const [player1Position, setPlayer1Position] = useState<Position>({\n x: arenaBounds.worldWidthMeters * -0.1, // 10% left of center (~0.8m for 8m arena)\n y: 0, // Centered\n });\n\n const [showPauseMenu, setShowPauseMenu] = useState(false);\n\n const handlePause = useCallback(() => {\n setShowPauseMenu(true);\n audio.playSFX(\"menu_select\");\n }, [audio]);\n\n const handleResume = useCallback(() => {\n setShowPauseMenu(false);\n audio.playSFX(\"menu_select\");\n }, [audio]);\n\n const handleRestart = useCallback(() => {\n\n setInternalRound(1);\n setMatchScore({ player1: 0, player2: 0 });\n matchScoreRef.current = { player1: 0, player2: 0 };\n\n combatActions.setRoundEnded(false);\n combatActions.setRoundStarted(false);\n combatActions.setRoundDisplayStatus(null);\n\n onPlayerUpdate(0, {\n health: 100,\n stamina: 100,\n ki: 100,\n consciousness: 100,\n pain: 0,\n balance: 100,\n combatState: CombatState.IDLE,\n isStunned: false,\n isBlocking: false,\n });\n onPlayerUpdate(1, {\n health: 100,\n stamina: 100,\n ki: 100,\n consciousness: 100,\n pain: 0,\n balance: 100,\n combatState: CombatState.IDLE,\n isStunned: false,\n isBlocking: false,\n });\n\n setPlayer1Position({\n x: arenaBounds.worldWidthMeters * -0.1, // 10% left of center in meters\n y: 0, // Centered\n });\n onPlayerUpdate(1, {\n position: {\n x: arenaBounds.worldWidthMeters * 0.1, // 10% right of center in meters\n y: 0, // Centered\n },\n });\n\n setShowPauseMenu(false);\n setShowRoundStart(true);\n\n audio.playSFX(\"menu_select\");\n }, [audio, combatActions, onPlayerUpdate, arenaBounds, setPlayer1Position]);\n\n const handleRoundTransitionComplete = useCallback(() => {\n if (import.meta.env.DEV) {\n console.log(\"[DEV] Round transition complete, checking match status\");\n }\n const currentScore = matchScoreRef.current;\n if (currentScore.player1 >= 2 || currentScore.player2 >= 2) {\n const matchWinner = currentScore.player1 >= 2 ? 0 : 1;\n if (import.meta.env.DEV) {\n console.log(\"[DEV] Match over, winner:\", matchWinner);\n }\n onGameEnd(matchWinner);\n return; // Don't start next round\n }\n\n combatActions.resetRoundState();\n\n setInternalRound((prev) => {\n const nextRound = prev + 1;\n if (import.meta.env.DEV) {\n console.log(\"[DEV] Incrementing round from\", prev, \"to\", nextRound);\n }\n setTimeout(() => {\n if (import.meta.env.DEV) {\n console.log(\n \"[DEV] Showing round start announcement for round\",\n nextRound,\n );\n }\n setShowRoundStart(true);\n }, ANNOUNCEMENT_FADE_OUT_DELAY);\n return nextRound;\n });\n\n onPlayerUpdate(0, {\n health: 100,\n stamina: 100,\n ki: 100,\n consciousness: 100,\n pain: 0,\n balance: 100,\n combatState: CombatState.IDLE,\n isStunned: false,\n isBlocking: false,\n });\n onPlayerUpdate(1, {\n health: 100,\n stamina: 100,\n ki: 100,\n consciousness: 100,\n pain: 0,\n balance: 100,\n combatState: CombatState.IDLE,\n isStunned: false,\n isBlocking: false,\n });\n\n setPlayer1Position({\n x: arenaBounds.worldWidthMeters * -0.1, // 10% left of center in meters\n y: 0, // Centered\n });\n onPlayerUpdate(1, {\n position: {\n x: arenaBounds.worldWidthMeters * 0.1, // 10% right of center in meters\n y: 0, // Centered\n },\n });\n }, [\n combatActions,\n onGameEnd,\n onPlayerUpdate,\n arenaBounds,\n setPlayer1Position,\n ]);\n\n const {\n showAnnouncement,\n roundWinner,\n currentRoundNumber: transitionRoundNumber,\n skipCountdown,\n startTransition,\n } = useRoundTransition(\n {\n announcementDuration: ROUND_ANNOUNCEMENT_TIMINGS.ANNOUNCEMENT_DURATION,\n countdownDuration: ROUND_ANNOUNCEMENT_TIMINGS.COUNTDOWN_DURATION,\n transitionDuration: ROUND_ANNOUNCEMENT_TIMINGS.TRANSITION_DURATION,\n },\n handleRoundTransitionComplete,\n );\n\n const player2Position = useMemo<Position>(() => {\n if (players.length >= 2 && players[1].position) {\n return players[1].position;\n }\n return {\n x: arenaBounds.worldWidthMeters * 0.1, // 10% right of center (~0.8m for 8m arena)\n y: 0, // Centered\n };\n }, [players, arenaBounds]);\n\n const playerPositions = useMemo<Position[]>(() => {\n return [player1Position, player2Position];\n }, [player1Position, player2Position]);\n\n const player1Position3D: [number, number, number] = useMemo(() => {\n return [playerPositions[0].x, 0, playerPositions[0].y];\n }, [playerPositions]);\n\n const player2Position3D: [number, number, number] = useMemo(() => {\n return [playerPositions[1].x, 0, playerPositions[1].y];\n }, [playerPositions]);\n\n\n const player2Rotation = useMemo(() => {\n const dx = player1Position3D[0] - player2Position3D[0];\n const dz = player1Position3D[2] - player2Position3D[2];\n return Math.atan2(dx, dz);\n }, [player1Position3D, player2Position3D]);\n\n const combatSystem = useMemo(() => new CombatSystem(), []);\n\n const balanceSystem = useMemo(() => new BalanceSystem(), []);\n\n const speedModifierSystem = useMemo(() => new SpeedModifierSystem(), []);\n\n const [player1SpeedModifiers, setPlayer1SpeedModifiers] = useState({\n finalSpeed: 6.0, // BASE_WALK_SPEED (6.0 m/s)\n baseSpeed: 6.0,\n finalAcceleration: 12.0, // BASE_ACCELERATION (12.0 m/s²)\n });\n const [player2SpeedModifiers, setPlayer2SpeedModifiers] = useState({\n finalSpeed: 6.0, // BASE_WALK_SPEED (6.0 m/s)\n baseSpeed: 6.0,\n finalAcceleration: 12.0, // BASE_ACCELERATION (12.0 m/s²)\n });\n\n const [player1WalkRunSpeeds, setPlayer1WalkRunSpeeds] = useState({\n walkSpeed: 6.0,\n runSpeed: 10.0,\n });\n\n useEffect(() => {\n const updateSpeedModifiers = () => {\n if (players.length >= 2) {\n const player1WalkModifiers =\n speedModifierSystem.calculateSpeedModifiers(\n players[0],\n MovementType.WALKING,\n false, // isCrouching\n );\n const player1RunModifiers = speedModifierSystem.calculateSpeedModifiers(\n players[0],\n MovementType.RUNNING,\n false, // isCrouching\n );\n\n setPlayer1SpeedModifiers({\n finalSpeed: player1WalkModifiers.finalSpeed,\n baseSpeed: player1WalkModifiers.baseSpeed,\n finalAcceleration: player1WalkModifiers.finalAcceleration,\n });\n\n setPlayer1WalkRunSpeeds({\n walkSpeed: player1WalkModifiers.finalSpeed,\n runSpeed: player1RunModifiers.finalSpeed,\n });\n\n const player2Modifiers = speedModifierSystem.calculateSpeedModifiers(\n players[1],\n MovementType.WALKING,\n false,\n );\n setPlayer2SpeedModifiers({\n finalSpeed: player2Modifiers.finalSpeed,\n baseSpeed: player2Modifiers.baseSpeed,\n finalAcceleration: player2Modifiers.finalAcceleration,\n });\n }\n };\n\n updateSpeedModifiers();\n\n const intervalId = setInterval(updateSpeedModifiers, 200);\n\n return () => clearInterval(intervalId);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [players]); // speedModifierSystem is memoized and never changes\n\n useEffect(() => {\n const updateTime = () => {\n setCurrentTime(Date.now());\n };\n\n const intervalId = setInterval(updateTime, 200);\n\n return () => clearInterval(intervalId);\n }, []);\n\n const calculateLegInjuryFactor = useCallback(\n (player: PlayerState): number => {\n if (!player.bodyPartHealth) return 0;\n\n const leftLeg = player.bodyPartHealth.legLeft ?? player.maxHealth;\n const rightLeg = player.bodyPartHealth.legRight ?? player.maxHealth;\n const maxHealth = player.maxHealth;\n\n const averageLegHealth = (leftLeg + rightLeg) / (2 * maxHealth);\n return Math.max(0, Math.min(1, 1.0 - averageLegHealth)); // 0 = healthy, 1 = critical\n },\n [],\n );\n\n const player1 = players.length > 0 ? players[0] : undefined;\n const player1Data = useMemo(() => {\n const p1 = player1 ?? createPlayerFromArchetype(PlayerArchetype.MUSA, 0);\n return {\n currentStance: p1.currentStance,\n legInjuryFactor: calculateLegInjuryFactor(p1),\n };\n }, [player1, calculateLegInjuryFactor]);\n\n const [player1AttackAnimation, setPlayer1AttackAnimation] = useState<\n string | undefined\n >(undefined);\n const [player2AttackAnimation, setPlayer2AttackAnimation] = useState<\n string | undefined\n >(undefined);\n\n const [player1TechniqueId, setPlayer1TechniqueId] = useState<\n string | undefined\n >(undefined);\n const [player2TechniqueId, setPlayer2TechniqueId] = useState<\n string | undefined\n >(undefined);\n\n const [player1Injuries, setPlayer1Injuries] = useState<readonly Injury[]>([]);\n const [player2Injuries, setPlayer2Injuries] = useState<readonly Injury[]>([]);\n\n useEffect(() => {\n return () => {\n setPlayer1Injuries([]);\n setPlayer2Injuries([]);\n };\n }, []);\n\n useEffect(() => {\n if (players.length >= 2) {\n const player1 = players[0];\n const player2 = players[1];\n\n if (\n player1?.health === player1?.maxHealth &&\n player2?.health === player2?.maxHealth\n ) {\n setPlayer1Injuries([]);\n setPlayer2Injuries([]);\n }\n }\n }, [players]);\n\n const handlePlayer1PositionChange = useCallback(\n (newPosition: Position) => {\n setPlayer1Position(newPosition);\n onPlayerUpdate(0, { position: newPosition });\n },\n [onPlayerUpdate],\n );\n\n const movementBounds = useMemo(\n () => ({\n worldWidthMeters: arenaBounds.worldWidthMeters,\n worldDepthMeters: arenaBounds.worldDepthMeters,\n }),\n [arenaBounds.worldWidthMeters, arenaBounds.worldDepthMeters],\n );\n\n\n const player1MovementTimeRef = useRef(0);\n const player1LastDirectionRef = useRef<{ x: number; y: number }>({\n x: 0,\n y: 0,\n });\n\n const [player1AccelerationBasedSpeed, setPlayer1AccelerationBasedSpeed] =\n useState(player1WalkRunSpeeds.walkSpeed);\n\n const player1IsRunning = isRunningSpeed(\n player1AccelerationBasedSpeed,\n player1WalkRunSpeeds.runSpeed,\n );\n\n const { isMoving: player1IsMoving, velocity: player1Velocity } =\n usePlayerMovement({\n enabled:\n !isPaused &&\n combatState.roundStarted &&\n !combatState.roundEnded &&\n matchCountdownComplete &&\n !showRoundStart,\n bounds: movementBounds, // Use memoized bounds object\n onPositionChange: handlePlayer1PositionChange, // Use memoized callback\n initialPositionMeters: player1Position,\n currentStance: player1Data.currentStance,\n legInjuryFactor: player1Data.legInjuryFactor,\n isRunning: player1IsRunning, // Use computed acceleration-based running state\n useTacticalSteps: false,\n maxSpeedOverride: player1AccelerationBasedSpeed,\n accelerationOverride: player1SpeedModifiers.finalAcceleration,\n });\n\n const player1Rotation = useMemo(() => {\n if (\n player1IsMoving &&\n player1Velocity &&\n (player1Velocity.x !== 0 || player1Velocity.y !== 0)\n ) {\n const movementRotation = Math.atan2(player1Velocity.x, player1Velocity.y);\n return movementRotation;\n } else {\n const dx = player2Position3D[0] - player1Position3D[0];\n const dz = player2Position3D[2] - player1Position3D[2];\n const targetRotation = Math.atan2(dx, dz);\n return targetRotation;\n }\n }, [player1IsMoving, player1Velocity, player1Position3D, player2Position3D]);\n\n const handleAttackRef = useRef<(() => void) | null>(null);\n\n const player1AnimationRef = useRef<ReturnType<\n typeof usePlayerAnimation\n > | null>(null);\n\n const validPlayersRefForAnimation = useRef<[PlayerState, PlayerState] | null>(\n null,\n );\n\n const player1HitTriggerFrameRef = useRef<number>(6);\n const player1AttackHitFiredRef = useRef<boolean>(false);\n\n const [player1AttackDuration, setPlayer1AttackDuration] =\n useState<number>(0.55);\n const [player2AttackDuration, setPlayer2AttackDuration] =\n useState<number>(0.55);\n\n const clearPlayer1AttackAnimation = useRef<() => void>(() => {\n setPlayer1AttackAnimation(undefined);\n setPlayer1TechniqueId(undefined);\n });\n const clearPlayer2AttackAnimation = useRef<() => void>(() => {\n setPlayer2AttackAnimation(undefined);\n setPlayer2TechniqueId(undefined);\n });\n\n const preparePlayer1AttackTiming = useCallback((animationName: string) => {\n const attackDuration = getAnimationDurationOrFallback(animationName);\n const attackFrames = Math.max(\n 1,\n Math.round(attackDuration * TARGET_ANIMATION_FPS),\n );\n player1HitTriggerFrameRef.current = Math.round(attackFrames * 0.4);\n player1AttackHitFiredRef.current = false;\n setPlayer1AttackDuration(attackDuration);\n return attackDuration;\n }, []);\n\n const player1AnimationEvents = useMemo<AnimationEvents>(\n () => ({\n onFrame: (frame, state) => {\n if (\n state === AnimationState.ATTACK &&\n frame >= player1HitTriggerFrameRef.current &&\n !player1AttackHitFiredRef.current\n ) {\n player1AttackHitFiredRef.current = true;\n handleAttackRef.current?.();\n }\n },\n onAnimationComplete: (state) => {\n if (\n state === AnimationState.ATTACK ||\n state === AnimationState.DEFEND\n ) {\n combatActions.setExecutingTechnique(false);\n if (state === AnimationState.ATTACK) {\n clearPlayer1AttackAnimation.current();\n }\n } else if (state === AnimationState.STANCE_CHANGE) {\n audio.playSFX(\"menu_select\");\n const players = validPlayersRefForAnimation.current;\n const currentStance = players?.[0]?.currentStance;\n if (currentStance && player1AnimationRef.current) {\n player1AnimationRef.current.transitionToStanceGuard(currentStance);\n }\n }\n },\n }),\n [combatActions, audio],\n );\n\n const player1Animation = usePlayerAnimation({\n events: player1AnimationEvents,\n });\n\n useEffect(() => {\n player1AnimationRef.current = player1Animation;\n }, [player1Animation]);\n\n const player2Animation = usePlayerAnimation({\n events: {\n onFrame: (frame, state) => {\n if (state === AnimationState.ATTACK && frame === 6) { /* attack frame hook */ }\n },\n onAnimationComplete: (state) => {\n if (state === AnimationState.ATTACK) {\n clearPlayer2AttackAnimation.current();\n }\n },\n },\n });\n\n const prevPlayer1IsMovingRef = useRef<boolean>(player1IsMoving);\n const prevPlayer1IsRunningRef = useRef<boolean>(player1IsRunning);\n useEffect(() => {\n const movementChanged = prevPlayer1IsMovingRef.current !== player1IsMoving;\n const runningChanged = prevPlayer1IsRunningRef.current !== player1IsRunning;\n\n if (movementChanged || runningChanged) {\n if (player1IsMoving) {\n const targetState = player1IsRunning\n ? AnimationState.RUN\n : AnimationState.WALK;\n if (player1Animation.currentState !== targetState) {\n player1Animation.transitionTo(targetState);\n }\n } else if (\n player1Animation.currentState === AnimationState.WALK ||\n player1Animation.currentState === AnimationState.RUN\n ) {\n player1Animation.transitionToStanceGuard(player1Data.currentStance);\n }\n prevPlayer1IsMovingRef.current = player1IsMoving;\n prevPlayer1IsRunningRef.current = player1IsRunning;\n }\n }, [\n player1IsMoving,\n player1IsRunning,\n player1Animation,\n player1Data.currentStance,\n ]);\n\n const MOVEMENT_DETECTION_THRESHOLD = 0.5;\n\n const player2Stance = useMemo(() => {\n return players[1]?.currentStance ?? TrigramStance.GEON;\n }, [players]);\n\n const prevPlayer2PositionRef = useRef(player2Position);\n useEffect(() => {\n const currentPos = playerPositions[1];\n const prevPos = prevPlayer2PositionRef.current;\n\n const isMoving =\n Math.abs(currentPos.x - prevPos.x) > MOVEMENT_DETECTION_THRESHOLD ||\n Math.abs(currentPos.y - prevPos.y) > MOVEMENT_DETECTION_THRESHOLD;\n\n if (isMoving) {\n if (\n player2Animation.currentState !== AnimationState.WALK &&\n player2Animation.currentState !== AnimationState.ATTACK\n ) {\n player2Animation.transitionTo(AnimationState.WALK);\n }\n } else {\n if (player2Animation.currentState === AnimationState.WALK) {\n player2Animation.transitionToStanceGuard(player2Stance);\n }\n }\n\n prevPlayer2PositionRef.current = currentPos;\n }, [playerPositions, player2Animation, player2Stance]);\n\n const validPlayers = useMemo((): [PlayerState, PlayerState] => {\n if (players.length === 0) {\n const player1 = createPlayerFromArchetype(PlayerArchetype.MUSA, 0);\n const player2 = createPlayerFromArchetype(PlayerArchetype.AMSALJA, 1);\n\n return [\n { ...player1, position: playerPositions[0] },\n { ...player2, position: playerPositions[1] },\n ];\n }\n\n const player1 = players[0];\n const player2 =\n players[1] ?? createPlayerFromArchetype(PlayerArchetype.AMSALJA, 1);\n\n return [\n { ...player1, position: playerPositions[0] },\n { ...player2, position: playerPositions[1] },\n ];\n }, [players, playerPositions]);\n\n const validPlayersRef = useRef<[PlayerState, PlayerState]>(validPlayers);\n useEffect(() => {\n validPlayersRef.current = validPlayers;\n validPlayersRefForAnimation.current = validPlayers;\n }, [validPlayers]);\n\n const getTechniqueAnimationType = useCallback(\n (techniqueId: string | undefined): AnimationType | undefined => {\n if (!techniqueId) return undefined;\n\n return getAnimationTypeForTechnique(techniqueId);\n },\n [],\n );\n\n const {\n player1Position: player1PositionWithAttackMovement,\n player2Position: player2PositionWithAttackMovement,\n } = useCombatAttackMovement({\n player1Attacking: player1Animation.currentState === AnimationState.ATTACK,\n player1AnimationType: getTechniqueAnimationType(player1TechniqueId),\n player1Stance: player1Data.currentStance,\n player1BasePosition: player1Position3D,\n player1AnimationDuration: player1AttackDuration,\n player2Attacking: player2Animation.currentState === AnimationState.ATTACK,\n player2AnimationType: getTechniqueAnimationType(player2TechniqueId),\n player2Stance: validPlayers[1].currentStance,\n player2BasePosition: player2Position3D,\n player2AnimationDuration: player2AttackDuration,\n });\n\n const [player1LocalStance, setPlayer1LocalStance] = useState<TrigramStance>(\n validPlayers[0].currentStance,\n );\n\n useEffect(() => {\n setPlayer1LocalStance(validPlayers[0].currentStance);\n }, [validPlayers]);\n\n const player1WithLocalStance = useMemo(\n (): PlayerState => ({\n ...validPlayers[0],\n currentStance: player1LocalStance,\n }),\n [validPlayers, player1LocalStance],\n );\n\n const startTransitionRef = useRef(startTransition);\n const internalRoundRef = useRef(internalRound);\n useEffect(() => {\n startTransitionRef.current = startTransition;\n internalRoundRef.current = internalRound;\n }, [startTransition, internalRound]);\n\n const addCombatMessage = useCallback(\n (korean: string, english: string) => {\n const message = `${korean} | ${english}`;\n combatActions.addCombatMessage(message);\n },\n [combatActions],\n );\n\n const handleTimeUp = useCallback(() => {\n if (!combatState.roundEnded) {\n combatActions.setRoundEnded(true);\n addCombatMessage(\"시간 종료!\", \"Time's Up!\");\n\n const currentPlayers = validPlayersRef.current;\n const player1Health = currentPlayers[0].health;\n const player2Health = currentPlayers[1].health;\n\n if (player1Health > player2Health) {\n updateMatchScore(0);\n startTransitionRef.current(currentPlayers[0], internalRoundRef.current); // Player 1 wins round\n } else if (player2Health > player1Health) {\n updateMatchScore(1);\n startTransitionRef.current(currentPlayers[1], internalRoundRef.current); // Player 2 wins round\n } else {\n startTransitionRef.current(null, internalRoundRef.current);\n }\n }\n }, [\n combatState.roundEnded,\n combatActions,\n addCombatMessage,\n updateMatchScore,\n ]);\n\n const handleTimeUpRef = useRef(handleTimeUp);\n useEffect(() => {\n handleTimeUpRef.current = handleTimeUp;\n }, [handleTimeUp]);\n\n const timerResetKey = `round-${internalRound}`;\n\n const timerState = useCombatTimer({\n initialTime: Math.max(0, timeRemaining),\n isPaused:\n isPaused ||\n !combatState.roundStarted ||\n combatState.roundEnded ||\n !matchCountdownComplete ||\n showRoundStart,\n onTimeUp: useCallback(() => handleTimeUpRef.current(), []),\n warningThreshold: 10,\n urgentThreshold: 5,\n resetKey: timerResetKey,\n });\n\n const startRound = useCallback(() => {\n if (import.meta.env.DEV) {\n console.log(\"[DEV] Starting round, setting roundStarted=true\");\n }\n combatActions.setRoundStarted(true);\n combatActions.setRoundEnded(false); // Ensure roundEnded is false\n addCombatMessage(\"라운드 시작!\", \"Round Start!\");\n\n const player = validPlayers[0];\n if (player?.archetype) {\n const playerArchetype = player.archetype.toLowerCase();\n combatAudio.playArchetypeMusic(playerArchetype, 2000);\n } else {\n combatAudio.playCombatMusic(2000);\n }\n }, [combatActions, addCombatMessage, validPlayers, combatAudio]);\n\n const hasAutoStartedRef = useRef(false);\n\n useEffect(() => {\n if (matchCountdownComplete && !hasAutoStartedRef.current) {\n hasAutoStartedRef.current = true;\n combatActions.setRoundStarted(true);\n addCombatMessage(\"라운드 시작!\", \"Round Start!\");\n\n const player = validPlayers[0];\n if (player?.archetype) {\n const playerArchetype = player.archetype.toLowerCase();\n combatAudio.playArchetypeMusic(playerArchetype, 2000);\n } else {\n combatAudio.playCombatMusic(2000);\n }\n }\n }, [\n matchCountdownComplete,\n combatActions,\n addCombatMessage,\n validPlayers,\n combatAudio,\n ]);\n\n const adaptiveDifficulty = useMemo(() => new AdaptiveDifficulty(), []);\n\n useEffect(() => {\n try {\n const savedMetrics = localStorage.getItem(\"ai_difficulty_metrics\");\n if (savedMetrics) {\n adaptiveDifficulty.importMetrics(savedMetrics);\n }\n } catch (err) {\n console.warn(\"Failed to load AI difficulty metrics:\", err);\n }\n\n return () => {\n try {\n const metrics = adaptiveDifficulty.exportMetrics();\n localStorage.setItem(\"ai_difficulty_metrics\", metrics);\n } catch (err) {\n console.warn(\"Failed to save AI difficulty metrics:\", err);\n }\n };\n }, [adaptiveDifficulty]);\n\n const aiPersonality = useMemo(\n () => getPersonalityByArchetype(validPlayers[1].archetype),\n [validPlayers],\n );\n\n const handleAIStanceChange = useCallback(\n (stance: TrigramStance) => {\n const currentStance = validPlayers[1].currentStance;\n\n player2Animation.transitionToStanceChange(currentStance, stance);\n\n onPlayerUpdate(1, { currentStance: stance });\n addCombatMessage(\n `AI 자세 변경: ${stance}`,\n `AI Stance Change: ${stance}`,\n );\n },\n [validPlayers, player2Animation, onPlayerUpdate, addCombatMessage],\n );\n\n const handleEffectComplete = useCallback(\n (effectId: string) => {\n combatActions.removeHitEffect(effectId);\n },\n [combatActions],\n );\n\n const createHitEffect = useCallback(\n (\n id: string,\n type: HitEffectType,\n position: Position,\n intensity: number,\n ): HitEffect => ({\n id,\n type,\n attackerId: \"player1\",\n defenderId: \"player2\",\n timestamp: Date.now(),\n duration: 1000,\n position,\n intensity,\n startTime: Date.now(),\n }),\n [],\n );\n\n const addHitEffect = useCallback(\n (type: HitEffectType, position: Position, intensity: number = 1) => {\n const effect = createHitEffect(\n `effect_${Date.now()}`,\n type,\n position,\n intensity,\n );\n combatActions.addHitEffect(effect);\n },\n [createHitEffect, combatActions],\n );\n\n const handlePlayerPositionUpdate = useCallback(\n (playerIndex: number, position: Position) => {\n if (playerIndex === 0) {\n setPlayer1Position(position);\n onPlayerUpdate(0, { position });\n } else if (playerIndex === 1) {\n onPlayerUpdate(1, { position });\n }\n },\n [onPlayerUpdate, setPlayer1Position],\n );\n\n const handleInjuryCreated = useCallback(\n (injury: Injury, targetPlayerIndex: number) => {\n const updateInjuries = (prev: readonly Injury[]): readonly Injury[] => {\n const recentHitTime = 5000; // 5 seconds\n const now = Date.now();\n\n const recentHit = prev.find(\n (existing) =>\n existing.region === injury.region &&\n now - existing.timestamp < recentHitTime &&\n existing.type === InjuryType.BRUISE &&\n injury.type === InjuryType.BRUISE,\n );\n\n if (recentHit) {\n const newHitCount = recentHit.hitCount + 1;\n const escalatedSeverity = Math.min(1.0, recentHit.severity + 0.15);\n\n return prev.map((existing) =>\n existing.id === recentHit.id\n ? {\n ...existing,\n hitCount: newHitCount,\n severity: escalatedSeverity,\n timestamp: now, // Update timestamp for progressive tracking\n }\n : existing,\n );\n }\n\n return [...prev, injury];\n };\n\n if (targetPlayerIndex === 0) {\n setPlayer1Injuries(updateInjuries);\n } else if (targetPlayerIndex === 1) {\n setPlayer2Injuries(updateInjuries);\n }\n },\n [],\n );\n\n const {\n handleAttack,\n handleDefend,\n handleStanceSwitch,\n handleStanceSideSwitch,\n handleAIAttack,\n handleAIDefend,\n handleAITechnique,\n moveAIPlayer,\n } = useCombatActions({\n validPlayers,\n playerPositions: [playerPositions[0], playerPositions[1]],\n combatState,\n combatActions,\n combatSystem,\n onPlayerUpdate,\n onPlayerPositionUpdate: handlePlayerPositionUpdate,\n onLateralityUpdate: (playerIndex, laterality) => {\n combatActions.setPlayerLateralityIndex(playerIndex as 0 | 1, laterality);\n },\n onInjuryCreated: handleInjuryCreated,\n addCombatMessage,\n addHitEffect,\n arenaBounds,\n combatAudio,\n playerAnimations: {\n player1: player1Animation,\n player2: player2Animation,\n },\n });\n\n useEffect(() => {\n handleAttackRef.current = handleAttack;\n }, [handleAttack]);\n\n const techniqueSelection = useTechniqueSelection({\n player: player1WithLocalStance,\n enabled:\n !isPaused &&\n combatState.roundStarted &&\n !combatState.roundEnded &&\n matchCountdownComplete &&\n !showRoundStart,\n onTechniqueExecute: useCallback(\n (technique: Technique) => {\n feedbackActions.showTechnique(\n technique.name.korean,\n technique.name.english,\n );\n\n const animationName = resolveTechniqueAnimation(technique);\n setPlayer1AttackAnimation(animationName);\n\n setPlayer1TechniqueId(technique.id);\n\n const attackDuration = preparePlayer1AttackTiming(animationName);\n player1Animation.transitionToAttack(attackDuration);\n combatActions.setExecutingTechnique(true);\n\n onPlayerUpdate(0, {\n stamina: Math.max(0, validPlayers[0].stamina - technique.staminaCost),\n ki: Math.max(0, validPlayers[0].ki - technique.kiCost),\n });\n\n handleAttack(technique);\n\n addCombatMessage(\n `${technique.name.korean} 사용!`,\n `Used ${technique.name.english}!`,\n );\n },\n [\n validPlayers,\n onPlayerUpdate,\n feedbackActions,\n handleAttack,\n addCombatMessage,\n player1Animation,\n combatActions,\n preparePlayer1AttackTiming,\n ],\n ),\n });\n\n const cooldownsMap = useMemo(() => {\n const map = new Map<string, number>();\n techniqueSelection.activeCooldowns.forEach((cd) => {\n map.set(cd.techniqueId, cd.remaining);\n });\n return map;\n }, [techniqueSelection.activeCooldowns]);\n\n const [previousStance, setPreviousStance] = useState<number>(0);\n\n const currentPlayerStance = validPlayers[0].currentStance;\n const currentStanceIndex = useMemo(() => {\n return STANCE_INDEX_MAP.get(currentPlayerStance) ?? 0;\n }, [currentPlayerStance]);\n\n const handleStanceChangeWithAnimation = useCallback(\n (newStance: TrigramStance) => {\n const currentStance = validPlayers[0].currentStance;\n\n // Full trigram stance change; laterality-only side switches use handleStanceSideSwitch.\n const success = player1Animation.transitionToStanceChange(\n currentStance,\n newStance,\n );\n\n if (success) {\n const prevStance = STANCE_INDEX_MAP.get(currentStance) ?? 0;\n setPreviousStance(prevStance);\n\n setPlayer1LocalStance(newStance);\n\n handleStanceSwitch(newStance);\n\n playStanceChangeSound();\n }\n },\n [validPlayers, player1Animation, handleStanceSwitch, playStanceChangeSound],\n );\n\n const player1Health = validPlayers[0].health;\n const player2Health = validPlayers[1].health;\n\n const lastPlayer2HealthRef = useRef(player2Health);\n useEffect(() => {\n const currentHealth = player2Health;\n const previousHealth = lastPlayer2HealthRef.current;\n const damageDone = previousHealth - currentHealth;\n\n if (damageDone > 0 && combatState.roundStarted && !combatState.roundEnded) {\n const getDamageType = (): \"critical\" | \"vital\" | \"normal\" => {\n if (damageDone >= 25) return \"critical\";\n if (damageDone >= 20) return \"vital\";\n return \"normal\";\n };\n const damageType = getDamageType();\n\n feedbackActions.addDamageNumber(\n Math.round(damageDone),\n playerPositions[1],\n damageType,\n );\n\n feedbackActions.incrementCombo();\n\n if (damageType === \"critical\") {\n feedbackActions.addActionFeedback(\n \"critical\",\n \"Critical!\",\n \"치명타!\",\n playerPositions[0],\n );\n }\n }\n\n lastPlayer2HealthRef.current = currentHealth;\n }, [\n player2Health,\n validPlayers,\n playerPositions,\n feedbackActions,\n combatState.roundStarted,\n combatState.roundEnded,\n ]);\n\n const lastPlayer1HealthRef = useRef(player1Health);\n useEffect(() => {\n const currentHealth = player1Health;\n const previousHealth = lastPlayer1HealthRef.current;\n const damageDone = previousHealth - currentHealth;\n\n if (damageDone > 0 && combatState.roundStarted && !combatState.roundEnded) {\n const damageType =\n damageDone >= 20 ? (\"critical\" as const) : (\"normal\" as const);\n feedbackActions.addDamageNumber(\n Math.round(damageDone),\n playerPositions[0],\n damageType,\n );\n }\n\n lastPlayer1HealthRef.current = currentHealth;\n }, [\n player1Health,\n validPlayers,\n playerPositions,\n feedbackActions,\n combatState.roundStarted,\n combatState.roundEnded,\n ]);\n\n const handleAttackWithFeedback = useCallback(() => {\n const basicTechnique = techniqueSelection.availableTechniques[0];\n const animationName = basicTechnique\n ? resolveTechniqueAnimation(basicTechnique)\n : \"jab\";\n setPlayer1AttackAnimation(animationName);\n if (basicTechnique?.id) {\n setPlayer1TechniqueId(basicTechnique.id);\n }\n\n const attackDuration = preparePlayer1AttackTiming(animationName);\n const success = player1Animation.transitionToAttack(attackDuration);\n if (success) {\n combatActions.setExecutingTechnique(true);\n } else {\n console.warn(\n \"Attack animation transition failed; executing attack logic directly.\",\n );\n handleAttack();\n }\n }, [\n player1Animation,\n combatActions,\n handleAttack,\n techniqueSelection.availableTechniques,\n preparePlayer1AttackTiming,\n ]);\n\n const handleDefendWithFeedback = useCallback(() => {\n const defenderPos = playerPositions[0];\n const success = player1Animation.transitionTo(AnimationState.DEFEND);\n if (success) {\n handleDefend();\n feedbackActions.addActionFeedback(\n \"blocked\",\n \"Blocked\",\n \"방어!\",\n defenderPos,\n );\n } else {\n console.warn(\n \"Defend animation transition failed; executing defend logic directly.\",\n );\n handleDefend();\n feedbackActions.addActionFeedback(\n \"blocked\",\n \"Blocked\",\n \"방어!\",\n defenderPos,\n );\n }\n }, [handleDefend, playerPositions, feedbackActions, player1Animation]);\n\n /**\n * Helper function to execute fallback recovery animation\n * when a specific recovery type cannot be performed.\n *\n * Determines the appropriate recovery type based on ground state\n * and transitions to that animation.\n *\n * @korean 대체회복실행\n */\n const executeFallbackRecovery = useCallback(() => {\n const groundState = balanceSystem.getGroundState(\n player1Animation.currentState,\n );\n if (groundState) {\n const recoveryType = determineRecoveryType(groundState);\n const animationState = getRecoveryAnimationState(recoveryType);\n player1Animation.transitionTo(animationState as AnimationState);\n }\n }, [balanceSystem, player1Animation]);\n\n const { queuedInputs, showHints } = useKeyboardControls({\n onStanceChange: useCallback(\n (stanceIndex: number) => {\n const stance = TRIGRAM_STANCES_ORDER[stanceIndex];\n if (stance) {\n handleStanceChangeWithAnimation(stance);\n }\n },\n [handleStanceChangeWithAnimation],\n ),\n onAction: useCallback(\n (action: string) => {\n switch (action) {\n case \"attack\":\n techniqueSelection.executeTechnique();\n break;\n case \"block\":\n handleDefendWithFeedback();\n break;\n case \"recovery_quick\": {\n executeFallbackRecovery();\n break;\n }\n case \"recovery_roll\": {\n const player1 = players[0];\n if (balanceSystem.canRecoverWithType(player1, \"roll_recovery\")) {\n const updatedPlayer = balanceSystem.applyRecoveryCost(\n player1,\n \"roll_recovery\",\n );\n onPlayerUpdate(0, { stamina: updatedPlayer.stamina });\n player1Animation.transitionTo(AnimationState.RECOVERY_ROLL);\n } else {\n audio.playSFX(\"menu_error\");\n const player1Pos = playerPositions[0];\n feedbackActions.addActionFeedback(\n \"blocked\",\n \"Not enough stamina!\",\n \"체력 부족!\",\n player1Pos,\n );\n executeFallbackRecovery();\n }\n break;\n }\n case \"recovery_defensive\": {\n player1Animation.transitionTo(AnimationState.RECOVERY_DEFENSIVE);\n break;\n }\n\n case \"footwork_circular_left\":\n case \"footwork_circular_right\":\n case \"footwork_slide_forward\":\n case \"footwork_slide_back\":\n case \"footwork_pivot_left\":\n case \"footwork_pivot_right\":\n case \"footwork_shuffle\":\n player1Animation.transitionTo(action as AnimationState);\n break;\n\n case \"stance_side_switch\":\n player1Animation.transitionTo(AnimationState.STANCE_SIDE_SWITCH);\n handleStanceSideSwitch(PLAYER_ONE_INDEX);\n break;\n\n }\n },\n [\n techniqueSelection,\n handleDefendWithFeedback,\n executeFallbackRecovery,\n balanceSystem,\n player1Animation,\n handleStanceSideSwitch,\n players,\n onPlayerUpdate,\n audio,\n feedbackActions,\n playerPositions,\n ],\n ),\n enabled:\n !isPaused &&\n !showPauseMenu &&\n combatState.roundStarted &&\n !combatState.roundEnded &&\n matchCountdownComplete &&\n !showRoundStart &&\n !combatState.isExecutingTechnique,\n currentStance: currentStanceIndex,\n playSFX: audio.playSFX,\n currentAnimationState: player1Animation.currentState,\n });\n\n const [stanceWheelExpanded, setStanceWheelExpanded] = useState(false);\n const activeMobileKeyRef = useRef<string | null>(null);\n\n /**\n * Mobile touch control handler - Converts VirtualDPad touch inputs to keyboard events\n *\n * Dispatches synthetic KeyboardEvents with proper properties to ensure compatibility\n * with usePlayerMovement hook. The synthetic events include:\n * - key: The character key (w/a/s/d)\n * - code: The physical key code (KeyW/KeyA/KeyS/KeyD)\n * - bubbles: true - Allows event to propagate through DOM\n * - cancelable: true - Allows event to be prevented\n *\n * These properties are essential for the keyboard event listeners in inputSystem.ts\n * to properly recognize and process the movement commands.\n *\n * @param direction - The D-pad direction or null\n * @param eventType - 'start' for press, 'end' for release\n */\n const handleMobileMove = useCallback(\n (direction: Direction | null, eventType: DPadEventType) => {\n const directionMap: Record<Direction, string> = {\n up: \"w\",\n \"up-right\": \"w\", // Diagonal simplified to primary direction\n right: \"d\",\n \"down-right\": \"s\",\n down: \"s\",\n \"down-left\": \"s\",\n left: \"a\",\n \"up-left\": \"w\",\n };\n\n if (eventType === \"start\" && direction) {\n if (\n activeMobileKeyRef.current &&\n activeMobileKeyRef.current !== directionMap[direction]\n ) {\n const prevKey = activeMobileKeyRef.current;\n window.dispatchEvent(\n new KeyboardEvent(\"keyup\", {\n key: prevKey,\n code: `Key${prevKey.toUpperCase()}`,\n bubbles: true,\n cancelable: true,\n }),\n );\n }\n\n const key = directionMap[direction];\n activeMobileKeyRef.current = key;\n window.dispatchEvent(\n new KeyboardEvent(\"keydown\", {\n key,\n code: `Key${key.toUpperCase()}`,\n bubbles: true,\n cancelable: true,\n }),\n );\n } else if (eventType === \"end\") {\n if (activeMobileKeyRef.current) {\n const key = activeMobileKeyRef.current;\n window.dispatchEvent(\n new KeyboardEvent(\"keyup\", {\n key,\n code: `Key${key.toUpperCase()}`,\n bubbles: true,\n cancelable: true,\n }),\n );\n activeMobileKeyRef.current = null;\n }\n }\n },\n [],\n );\n\n const handleMobileAttack = useCallback(() => {\n techniqueSelection.executeTechnique();\n }, [techniqueSelection]);\n\n const handleMobileBlock = useCallback(\n (eventType: ButtonEventType) => {\n if (eventType === \"start\") {\n handleDefendWithFeedback();\n }\n },\n [handleDefendWithFeedback],\n );\n\n const handleMobileStanceChange = useCallback(\n (stanceIndex: number) => {\n const stance = TRIGRAM_STANCES_ORDER[stanceIndex];\n if (stance) {\n handleStanceChangeWithAnimation(stance);\n }\n },\n [handleStanceChangeWithAnimation],\n );\n\n const handleMobileGesture = useCallback(\n (gesture: GestureEvent) => {\n switch (gesture.type) {\n case \"swipe-right\":\n window.dispatchEvent(new KeyboardEvent(\"keydown\", { key: \"d\" }));\n setTimeout(() => {\n window.dispatchEvent(new KeyboardEvent(\"keyup\", { key: \"d\" }));\n }, 100);\n break;\n case \"swipe-left\":\n window.dispatchEvent(new KeyboardEvent(\"keydown\", { key: \"a\" }));\n setTimeout(() => {\n window.dispatchEvent(new KeyboardEvent(\"keyup\", { key: \"a\" }));\n }, 100);\n break;\n case \"swipe-up\":\n techniqueSelection.executeTechnique();\n break;\n case \"swipe-down\":\n techniqueSelection.executeTechnique();\n break;\n case \"two-finger-tap\":\n audio.playSFX(\"menu_select\");\n break;\n }\n },\n [techniqueSelection, audio],\n );\n\n const toggleStanceWheel = useCallback(() => {\n setStanceWheelExpanded((prev) => !prev);\n }, []);\n\n const mobileControlsEnabled =\n isMobile &&\n !isPaused &&\n !showPauseMenu &&\n combatState.roundStarted &&\n !combatState.roundEnded &&\n matchCountdownComplete &&\n !showRoundStart &&\n !combatState.isExecutingTechnique;\n\n\n useEffect(() => {\n if (isPaused) return;\n\n if (timeRemaining <= 0 && !combatState.roundEnded) {\n combatActions.setRoundEnded(true);\n combatActions.setRoundStarted(false);\n combatActions.setRoundDisplayStatus(\"end\");\n\n combatAudio.stopCombatMusic(1000);\n\n const winner = validPlayers[0].health > validPlayers[1].health ? 0 : 1;\n const roundWinner = validPlayers[winner];\n\n updateMatchScore(winner);\n\n addCombatMessage(\"라운드 종료!\", \"Round Over!\");\n\n setTimeout(() => {\n startTransition(roundWinner, internalRound);\n }, 1500);\n }\n }, [\n timeRemaining,\n combatState.roundEnded,\n combatState.roundStarted,\n validPlayers,\n onGameEnd,\n addCombatMessage,\n internalRound,\n isPaused,\n combatActions,\n combatAudio,\n startTransition,\n updateMatchScore,\n ]);\n\n const executeAIActionCallbackRef = useRef<\n | ((\n action: string,\n targetPos?: Position,\n selectedTechnique?: KoreanTechnique,\n targetVitalPoint?: string,\n ) => void)\n | undefined\n >(undefined);\n\n const { updateDifficultyTarget } = useAICombat({\n player: validPlayers[1],\n opponent: validPlayers[0],\n personality: aiPersonality,\n adaptiveDifficulty,\n isPaused,\n roundStarted: combatState.roundStarted,\n roundEnded: combatState.roundEnded,\n arenaBounds,\n onExecuteAction: (action, targetPos, selectedTechnique, targetVitalPoint) =>\n executeAIActionCallbackRef.current?.(\n action,\n targetPos,\n selectedTechnique,\n targetVitalPoint,\n ),\n onStanceChange: handleAIStanceChange,\n onLateralityChange: () => handleStanceSideSwitch(1), // AI player (index 1)\n playerLaterality: combatState.playerLaterality[1], // AI's own laterality\n opponentLaterality: combatState.playerLaterality[0], // Opponent (human) laterality\n });\n\n const currentDifficultyTier = useMemo(\n () => adaptiveDifficulty.getDifficultyTier(),\n [adaptiveDifficulty],\n );\n\n useEffect(() => {\n if (!combatState.roundEnded || internalRound < 1) {\n return;\n }\n\n const roundsCompleted = internalRound;\n if (roundsCompleted % 2 === 0) {\n const player1 = validPlayersRef.current[0];\n\n adaptiveDifficulty.updateSkillMetrics({\n hitsLanded: player1.hitsLanded ?? 0,\n totalAttacks: (player1.hitsLanded ?? 0) + (player1.misses ?? 0),\n combosExecuted: 0, // TODO (Phase 2): Track combo count in PlayerState\n perfectBlockCount: 0, // TODO (Phase 2): Track perfect blocks in PlayerState\n avgReactionTimeMs: 600, // TODO (Phase 2): Track player reaction time\n vitalPointsHit: 0, // TODO (Phase 2): Track vital point hits\n effectiveStanceChanges: 0, // TODO (Phase 2): Track stance changes\n damageDealt: player1.totalDamageDealt ?? 0,\n damageTaken: player1.totalDamageReceived ?? 0,\n });\n\n const newParams = adaptiveDifficulty.getDifficultyParameters();\n updateDifficultyTarget(newParams);\n\n if (import.meta.env.DEV) {\n const tier = adaptiveDifficulty.getDifficultyTier();\n console.log(\n `[DEV] Difficulty adjusted after round ${roundsCompleted}, new tier: ${tier}`,\n );\n }\n }\n }, [\n combatState.roundEnded,\n internalRound,\n adaptiveDifficulty,\n updateDifficultyTarget,\n ]);\n\n const executeAIActionCallback = useCallback(\n (\n action: string,\n targetPos?: Position,\n selectedTechnique?: KoreanTechnique,\n targetVitalPoint?: string,\n ) => {\n const aiStance = validPlayers[1]?.currentStance ?? TrigramStance.GEON;\n const aiFallbackTechnique = TRIGRAM_TECHNIQUES[aiStance]?.[0];\n const aiFallbackAnim = aiFallbackTechnique\n ? resolveTechniqueAnimation(aiFallbackTechnique)\n : \"jab\";\n switch (action) {\n case \"attack\":\n if (selectedTechnique) {\n const p2AttackAnimName = resolveTechniqueAnimation(selectedTechnique);\n setPlayer2AttackAnimation(p2AttackAnimName);\n\n if (selectedTechnique.id) {\n setPlayer2TechniqueId(selectedTechnique.id);\n }\n const p2AttackAnim = getAnimation(p2AttackAnimName);\n const p2AttackDur = p2AttackAnim?.duration ?? 0.55;\n setPlayer2AttackDuration(p2AttackDur);\n player2Animation.transitionToAttack(p2AttackDur);\n } else {\n setPlayer2AttackAnimation(aiFallbackAnim);\n if (aiFallbackTechnique?.id) {\n setPlayer2TechniqueId(aiFallbackTechnique.id);\n }\n const p2FallbackAnim = getAnimation(aiFallbackAnim);\n const p2FallbackDur = p2FallbackAnim?.duration ?? 0.55;\n setPlayer2AttackDuration(p2FallbackDur);\n player2Animation.transitionToAttack(p2FallbackDur);\n }\n handleAIAttack(selectedTechnique, targetVitalPoint);\n break;\n case \"defend\":\n player2Animation.transitionTo(AnimationState.DEFEND);\n handleAIDefend();\n break;\n case \"technique\":\n case \"combo\":\n if (selectedTechnique) {\n const p2TechAnimName = resolveTechniqueAnimation(selectedTechnique);\n setPlayer2AttackAnimation(p2TechAnimName);\n\n if (selectedTechnique.id) {\n setPlayer2TechniqueId(selectedTechnique.id);\n }\n const p2TechAnim = getAnimation(p2TechAnimName);\n const p2TechDur = p2TechAnim?.duration ?? 0.6;\n setPlayer2AttackDuration(p2TechDur);\n player2Animation.transitionToAttack(p2TechDur);\n } else {\n setPlayer2AttackAnimation(aiFallbackAnim);\n if (aiFallbackTechnique?.id) {\n setPlayer2TechniqueId(aiFallbackTechnique.id);\n }\n const p2FallbackAnim = getAnimation(aiFallbackAnim);\n const p2FallbackDur = p2FallbackAnim?.duration ?? 0.6;\n setPlayer2AttackDuration(p2FallbackDur);\n player2Animation.transitionToAttack(p2FallbackDur);\n }\n handleAITechnique(selectedTechnique, targetVitalPoint);\n break;\n case \"approach\":\n case \"retreat\":\n case \"circle\":\n if (targetPos) {\n moveAIPlayer(targetPos);\n }\n break;\n case \"feint\":\n {\n const playerPos = validPlayers[0].position;\n const feintOffsetMeters = 0.5;\n const feintPos = {\n x: playerPos.x + (Math.random() - 0.5) * feintOffsetMeters,\n y: playerPos.y + (Math.random() - 0.5) * feintOffsetMeters,\n };\n moveAIPlayer(feintPos);\n addCombatMessage(\"AI 페인트\", \"AI Feint\");\n\n setTimeout(() => {\n if (\n !combatState.roundEnded &&\n combatState.roundStarted &&\n validPlayers.length >= 2\n ) {\n const currentPlayerPos = validPlayers[0].position;\n const currentAiPos = validPlayers[1].position;\n const dx = currentAiPos.x - currentPlayerPos.x;\n const dy = currentAiPos.y - currentPlayerPos.y;\n const dist = Math.sqrt(dx * dx + dy * dy) || 1;\n const retreatDistanceMeters = 0.8;\n const halfWidth = arenaBounds.worldWidthMeters / 2;\n const halfDepth = arenaBounds.worldDepthMeters / 2;\n const retreatPos = {\n x: Math.max(\n -halfWidth + 0.5, // 0.5m from edge\n Math.min(\n halfWidth - 0.5,\n currentPlayerPos.x + (dx / dist) * retreatDistanceMeters,\n ),\n ),\n y: Math.max(\n -halfDepth + 0.5, // 0.5m from edge\n Math.min(\n halfDepth - 0.5,\n currentPlayerPos.y + (dy / dist) * retreatDistanceMeters,\n ),\n ),\n };\n moveAIPlayer(retreatPos);\n }\n }, 200);\n }\n break;\n case \"counter\":\n if (selectedTechnique) {\n const p2CounterAnimName = resolveTechniqueAnimation(selectedTechnique);\n setPlayer2AttackAnimation(p2CounterAnimName);\n\n if (selectedTechnique.id) {\n setPlayer2TechniqueId(selectedTechnique.id);\n }\n const p2CounterAnim = getAnimation(p2CounterAnimName);\n const p2CounterDur = p2CounterAnim?.duration ?? 0.6;\n setPlayer2AttackDuration(p2CounterDur);\n player2Animation.transitionToAttack(p2CounterDur);\n } else {\n setPlayer2AttackAnimation(aiFallbackAnim);\n if (aiFallbackTechnique?.id) {\n setPlayer2TechniqueId(aiFallbackTechnique.id);\n }\n const p2FallbackAnim = getAnimation(aiFallbackAnim);\n const p2FallbackDur = p2FallbackAnim?.duration ?? 0.6;\n setPlayer2AttackDuration(p2FallbackDur);\n player2Animation.transitionToAttack(p2FallbackDur);\n }\n handleAIAttack(selectedTechnique, targetVitalPoint);\n addCombatMessage(\"AI 반격!\", \"AI Counter!\");\n break;\n }\n },\n [\n handleAIAttack,\n handleAIDefend,\n handleAITechnique,\n moveAIPlayer,\n addCombatMessage,\n validPlayers,\n arenaBounds,\n combatState.roundEnded,\n combatState.roundStarted,\n player2Animation,\n ],\n );\n\n useEffect(() => {\n executeAIActionCallbackRef.current = executeAIActionCallback;\n }, [executeAIActionCallback]);\n\n useEffect(() => {\n if (combatState.roundEnded && validPlayers.length === 2) {\n const player = validPlayers[0];\n const totalAttacks = (player.hitsLanded ?? 0) + (player.hitsTaken ?? 0);\n\n if (totalAttacks === 0) return;\n\n adaptiveDifficulty.updateSkillMetrics({\n hitsLanded: player.hitsLanded ?? 0,\n totalAttacks,\n combosExecuted: player.comboCount ?? 0,\n perfectBlockCount: 0,\n avgReactionTimeMs: 500,\n vitalPointsHit: player.vitalPointHits ?? 0,\n effectiveStanceChanges: 0,\n damageDealt: player.totalDamageDealt ?? 0,\n damageTaken: player.totalDamageReceived ?? 0,\n });\n }\n }, [combatState.roundEnded, adaptiveDifficulty, validPlayers]);\n\n const checkGameEnd = useCallback(() => {\n if (combatState.roundEnded) return;\n\n const p1Defeated = validPlayers[0].health <= 0;\n const p2Defeated = validPlayers[1].health <= 0;\n\n if (p1Defeated || p2Defeated) {\n combatActions.setRoundEnded(true);\n combatActions.setRoundStarted(false);\n combatActions.setRoundDisplayStatus(\"ko\");\n const winner = p1Defeated ? 1 : 0;\n const roundWinner = validPlayers[winner];\n\n updateMatchScore(winner);\n\n addCombatMessage(\n p1Defeated ? \"플레이어 1 패배\" : \"플레이어 1 승리!\",\n p1Defeated ? \"Player 1 Defeated\" : \"Player 1 Victory!\",\n );\n\n setTimeout(() => {\n startTransition(roundWinner, internalRound);\n }, 1500);\n }\n }, [\n validPlayers,\n addCombatMessage,\n combatState.roundEnded,\n combatActions,\n internalRound,\n startTransition,\n updateMatchScore,\n ]);\n\n useEffect(() => {\n checkGameEnd();\n }, [player1Health, player2Health, checkGameEnd]);\n\n useEffect(() => {\n const handleCombatInput = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") {\n event.preventDefault();\n if (showPauseMenu) {\n handleResume();\n } else {\n handlePause();\n }\n return;\n }\n\n if (isPaused || showPauseMenu) {\n return;\n }\n\n if (!matchCountdownComplete || showRoundStart) {\n return;\n }\n\n if (\n !combatState.roundStarted ||\n combatState.roundEnded ||\n combatState.isExecutingTechnique\n ) {\n return;\n }\n\n const key = event.key.toLowerCase();\n\n if (key >= \"1\" && key <= \"8\") {\n const stanceIndex = parseInt(key) - 1;\n const stances: TrigramStance[] = [\n TrigramStance.GEON,\n TrigramStance.TAE,\n TrigramStance.LI,\n TrigramStance.JIN,\n TrigramStance.SON,\n TrigramStance.GAM,\n TrigramStance.GAN,\n TrigramStance.GON,\n ];\n handleStanceSwitch(stances[stanceIndex]);\n event.preventDefault();\n }\n\n if (key === \" \") {\n handleAttackWithFeedback();\n event.preventDefault();\n }\n\n if (event.key === \"Shift\") {\n handleDefendWithFeedback();\n event.preventDefault();\n }\n\n if (event.key === \"f\" || event.key === \"F\") {\n handleStanceSideSwitch(0); // Human player\n event.preventDefault();\n }\n };\n\n window.addEventListener(\"keydown\", handleCombatInput);\n return () => window.removeEventListener(\"keydown\", handleCombatInput);\n }, [\n combatState.roundStarted,\n combatState.roundEnded,\n combatState.isExecutingTechnique,\n matchCountdownComplete,\n showRoundStart,\n isPaused,\n showPauseMenu,\n handleStanceSwitch,\n handleStanceSideSwitch,\n handleAttackWithFeedback,\n handleDefendWithFeedback,\n handlePause,\n handleResume,\n ]);\n\n const player1MovementState = useMemo(() => {\n if (!validPlayers[0]?.bodyPartHealth) {\n return {\n statusText: { korean: \"정상\", english: \"Normal\" },\n isLimping: false,\n isSevereLimp: false,\n };\n }\n\n const result = injuryMovementModifier.calculateMovementSpeed(\n 1.0,\n validPlayers[0].bodyPartHealth,\n validPlayers[0].currentStance ?? TrigramStance.GEON,\n validPlayers[0].pain ?? 0,\n );\n\n return {\n statusText: result.statusText,\n isLimping: result.isLimping,\n isSevereLimp: result.isSevereLimp,\n speedMultiplier: result.speedMultiplier,\n };\n }, [validPlayers]);\n\n const player2MovementState = useMemo(() => {\n if (!validPlayers[1]?.bodyPartHealth) {\n return {\n statusText: { korean: \"정상\", english: \"Normal\" },\n isLimping: false,\n isSevereLimp: false,\n };\n }\n\n const result = injuryMovementModifier.calculateMovementSpeed(\n 1.0,\n validPlayers[1].bodyPartHealth,\n validPlayers[1].currentStance ?? TrigramStance.GEON,\n validPlayers[1].pain ?? 0,\n );\n\n return {\n statusText: result.statusText,\n isLimping: result.isLimping,\n isSevereLimp: result.isSevereLimp,\n speedMultiplier: result.speedMultiplier,\n };\n }, [validPlayers]);\n\n return (\n <div\n style={{\n width: `${width}px`,\n height: `${height}px`,\n position: \"relative\",\n backgroundColor: toHexColor(KOREAN_COLORS.UI_BACKGROUND_DARK),\n overflow: \"hidden\", // Prevent content from extending beyond container\n }}\n data-testid=\"combat-screen\"\n >\n {/* Three.js Canvas for 3D rendering */}\n <Canvas\n style={{ width: `${width}px`, height: `${height}px` }}\n camera={{\n position: cameraConfig.position,\n fov: cameraConfig.fov,\n near: cameraConfig.near,\n far: cameraConfig.far,\n }}\n gl={{\n antialias: renderConfig.antialias,\n alpha: false,\n powerPreference: \"high-performance\",\n failIfMajorPerformanceCaveat: false,\n }}\n dpr={renderConfig.dpr}\n shadows={false} // Temporarily disable shadows\n onCreated={({ gl }) => {\n gl.setClearColor(theme.colors.UI_BACKGROUND_DARK, 1);\n }}\n >\n {/* Lighting - CombatArena3D provides ambient, we add directional for shadows */}\n <ambientLight intensity={0.6} />\n <directionalLight position={[10, 10, 5]} intensity={1.2} />\n\n {/* Adaptive Quality Wrapper monitors FPS and adjusts quality */}\n <AdaptiveQualityWrapper\n enabled={shouldEnableAdaptiveQuality}\n isMobile={isMobile}\n >\n {/* Performance overlay (dev mode) - controlled by showPerformanceOverlay prop */}\n {showPerformanceOverlay && !isMobile && !showPerformanceMonitor && (\n <PerformanceOverlay3D />\n )}\n\n {/* Combat Arena 3D Environment - uses physics-based world dimensions */}\n <CombatArena3D\n lighting=\"cyberpunk\"\n scale={arenaBounds.scale}\n worldWidthMeters={arenaBounds.worldWidthMeters}\n worldDepthMeters={arenaBounds.worldDepthMeters}\n />\n\n {/* Animation updater - updates both player animations at 60fps */}\n <AnimationUpdater\n player1Animation={player1Animation}\n player2Animation={player2Animation}\n />\n\n {/* Acceleration updater - tracks player 1 movement time and updates speed */}\n <AccelerationUpdater\n isMoving={player1IsMoving}\n velocity={player1Velocity}\n movementTimeRef={player1MovementTimeRef}\n lastDirectionRef={player1LastDirectionRef}\n onSpeedUpdate={setPlayer1AccelerationBasedSpeed}\n walkSpeed={player1WalkRunSpeeds.walkSpeed}\n runSpeed={player1WalkRunSpeeds.runSpeed}\n />\n\n {/* Player 1 (Human) */}\n <Player3DWithTransitions\n {...convertPlayerStateToProps(\n validPlayers[0],\n player1PositionWithAttackMovement,\n player1Rotation,\n {\n isMobile,\n facing: \"right\",\n enableFacialExpressions: true,\n enableEyeTracking: true,\n opponentPosition: player2PositionWithAttackMovement,\n },\n )}\n currentAnimation={animationStateToPlayerAnimation(\n player1Animation.currentState,\n )}\n attackAnimation={player1AttackAnimation}\n laterality={combatState.playerLaterality[0]}\n enableTransitionEffects={!isMobile}\n enableStanceSymbol={!isMobile}\n enableStanceAudio={true}\n />\n\n {/* Player 2 (AI) */}\n <Player3DWithTransitions\n {...convertPlayerStateToProps(\n validPlayers[1],\n player2PositionWithAttackMovement,\n player2Rotation,\n {\n isMobile,\n facing: \"right\",\n enableFacialExpressions: true,\n enableEyeTracking: true,\n opponentPosition: player1PositionWithAttackMovement,\n },\n )}\n currentAnimation={animationStateToPlayerAnimation(\n player2Animation.currentState,\n )}\n attackAnimation={player2AttackAnimation}\n laterality={combatState.playerLaterality[1]}\n enableTransitionEffects={!isMobile}\n enableStanceSymbol={!isMobile}\n enableStanceAudio={true}\n />\n\n {/* Movement Status Indicators - Korean/English Bilingual */}\n {/* Player 1 Movement Status */}\n {(player1MovementState.isLimping ||\n player1MovementState.isSevereLimp) && (\n <Html\n position={[\n player1Position3D[0],\n player1Position3D[1] + 2.5,\n player1Position3D[2],\n ]}\n center\n data-testid=\"player1-movement-status\"\n >\n <div\n style={{\n fontSize: isMobile ? \"12px\" : \"14px\",\n color: player1MovementState.isSevereLimp\n ? toHexColor(KOREAN_COLORS.TEXT_ERROR)\n : toHexColor(KOREAN_COLORS.ACCENT_GOLD),\n fontFamily: FONT_FAMILY.KOREAN,\n fontWeight: \"bold\",\n textShadow: \"0 0 4px rgba(0,0,0,0.8)\",\n background: \"rgba(0, 0, 0, 0.6)\",\n padding: \"4px 8px\",\n borderRadius: \"4px\",\n whiteSpace: \"nowrap\",\n }}\n >\n {player1MovementState.statusText.korean} |{\" \"}\n {player1MovementState.statusText.english}\n </div>\n </Html>\n )}\n\n {/* Player 2 Movement Status */}\n {(player2MovementState.isLimping ||\n player2MovementState.isSevereLimp) && (\n <Html\n position={[\n player2Position3D[0],\n player2Position3D[1] + 2.5,\n player2Position3D[2],\n ]}\n center\n data-testid=\"player2-movement-status\"\n >\n <div\n style={{\n fontSize: isMobile ? \"12px\" : \"14px\",\n color: player2MovementState.isSevereLimp\n ? toHexColor(KOREAN_COLORS.TEXT_ERROR)\n : toHexColor(KOREAN_COLORS.ACCENT_GOLD),\n fontFamily: FONT_FAMILY.KOREAN,\n fontWeight: \"bold\",\n textShadow: \"0 0 4px rgba(0,0,0,0.8)\",\n background: \"rgba(0, 0, 0, 0.6)\",\n padding: \"4px 8px\",\n borderRadius: \"4px\",\n whiteSpace: \"nowrap\",\n }}\n >\n {player2MovementState.statusText.korean} |{\" \"}\n {player2MovementState.statusText.english}\n </div>\n </Html>\n )}\n\n {/* Trauma Overlays - Injury Visualization (외상 오버레이 - 부상 시각화) */}\n {/* Player 1 Injuries */}\n <TraumaOverlay3D\n playerId=\"player\"\n health={validPlayers[0].health}\n injuries={player1Injuries}\n characterPosition={player1Position3D}\n isMobile={isMobile}\n showFractures={true}\n />\n\n {/* Player 2 Injuries */}\n <TraumaOverlay3D\n playerId=\"enemy\"\n health={validPlayers[1].health}\n injuries={player2Injuries}\n characterPosition={player2Position3D}\n isMobile={isMobile}\n showFractures={true}\n />\n\n {/* Hit Effects */}\n <HitEffects3D\n effects={combatState.hitEffects}\n onEffectComplete={handleEffectComplete}\n arenaBounds={arenaBounds}\n />\n\n {/* Combat Particle Effects - Blood viscosity, organ damage, audio (전투 입자 효과) */}\n <CombatParticleEffects3D\n hitEffects={combatState.hitEffects}\n enabled={true}\n isMobile={isMobile}\n />\n\n {/* Vital Point Overlay - Show on both players when V is pressed */}\n {overlayVisible && (\n <>\n {/* Player 1 Vital Points */}\n <VitalPointMarkers3D\n position={player1Position3D}\n visible={overlayVisible}\n severityFilter={severityFilters}\n regionFilter={regionFilter}\n searchQuery={searchQuery}\n showLabels={showLabels}\n scale={scale}\n animated={animated}\n onPointClick={() => {\n }}\n />\n\n {/* Player 2 Vital Points */}\n <VitalPointMarkers3D\n position={player2Position3D}\n visible={overlayVisible}\n severityFilter={severityFilters}\n regionFilter={regionFilter}\n searchQuery={searchQuery}\n showLabels={showLabels}\n scale={scale}\n animated={animated}\n onPointClick={() => {\n }}\n />\n\n {/* Vital Point Overlay Controls - only visible when overlay is active */}\n <VitalPointOverlayControlsHtml\n screenPosition={{\n top: `${combatTopHudHeight + layoutConstants.padding}px`,\n left: `${layoutConstants.padding}px`,\n }}\n visible={overlayVisible}\n onVisibleChange={setOverlayVisible}\n severityFilters={severityFilters}\n onSeverityFiltersChange={setSeverityFilters}\n regionFilter={regionFilter}\n onRegionFilterChange={setRegionFilter}\n searchQuery={searchQuery}\n onSearchQueryChange={setSearchQuery}\n showLabels={showLabels}\n onShowLabelsChange={setShowLabels}\n animated={animated}\n onAnimatedChange={setAnimated}\n scale={scale}\n onScaleChange={setScale}\n isMobile={isMobile}\n />\n </>\n )}\n\n {/* Action Feedback - Damage Numbers */}\n <DamageNumbers\n damages={feedbackState.damageNumbers}\n isMobile={isMobile}\n arenaBounds={arenaBounds}\n />\n\n {/* Action Feedback - Action Indicators */}\n <ActionFeedback\n feedbacks={feedbackState.actionFeedbacks}\n isMobile={isMobile}\n arenaBounds={arenaBounds}\n />\n\n {/* Combo Counter */}\n <ComboCounter combo={feedbackState.comboCount} isMobile={isMobile} />\n\n {/* Technique Name Display */}\n {feedbackState.currentTechnique && (\n <TechniqueName\n korean={feedbackState.currentTechnique.korean}\n english={feedbackState.currentTechnique.english}\n isMobile={isMobile}\n onComplete={() => feedbackActions.hideTechnique()}\n />\n )}\n\n {/* Performance Overlay (Development Only) - Toggle with P key */}\n {import.meta.env.DEV && showPerformanceMonitor && (\n <PerformanceOverlay3D visible={true} />\n )}\n\n {/* Visual Feedback Components for Keyboard Controls */}\n <StanceChangeIndicator\n currentStance={currentStanceIndex}\n previousStance={previousStance}\n isMobile={isMobile}\n />\n\n <KeyboardHints\n visible={showHints}\n currentStance={currentStanceIndex}\n isMobile={isMobile}\n />\n\n <InputBufferDisplay queuedInputs={queuedInputs} isMobile={isMobile} />\n\n {/* 3D Balance Indicators - Positioned below top HUD, to the right of side HUDs */}\n {/* Player 1 Balance Indicator - Upper left area, below top HUD */}\n {validPlayers[0] && (\n <BalanceIndicatorOverlayHtml\n player={validPlayers[0] as BalancePlayerState}\n currentTime={currentTime}\n position={[\n -2.5, // Left side of arena (to the right of left HUD in 3D space)\n 2.5, // Upper area (below top HUD)\n -1.0, // Slightly forward toward camera\n ]}\n isMobile={isMobile}\n />\n )}\n\n {/* Player 2 Balance Indicator - Upper right area, below top HUD */}\n {validPlayers[1] && (\n <BalanceIndicatorOverlayHtml\n player={validPlayers[1] as BalancePlayerState}\n currentTime={currentTime}\n position={[\n 2.5, // Right side of arena (to the left of right HUD in 3D space)\n 2.5, // Upper area (below top HUD)\n -1.0, // Slightly forward toward camera\n ]}\n isMobile={isMobile}\n />\n )}\n\n {/* Mobile Touch Controls moved outside Canvas - using MobileControlsOverlay for reliable touch events */}\n\n {/* Performance Monitoring - FPS display (dev mode, toggle with P key) */}\n {process.env.NODE_ENV === \"development\" && showPerformanceMonitor && (\n <FPSMonitor\n enabled={true}\n warningThreshold={50}\n criticalThreshold={30}\n />\n )}\n </AdaptiveQualityWrapper>\n\n {/* Post-processing Effects - desktop high tier only for Android WebGL stability */}\n {renderConfig.postProcessing && (\n <EffectComposer multisampling={4}>\n <Bloom\n luminanceThreshold={0.9}\n luminanceSmoothing={0.9}\n mipmapBlur\n intensity={0.8}\n radius={0.4}\n />\n <Noise opacity={0.03} />\n <Vignette eskil={false} offset={0.1} darkness={0.3} />\n </EffectComposer>\n )}\n </Canvas>\n\n {/* Html UI Overlays (positioned absolutely over Canvas) */}\n <div\n style={{\n position: \"absolute\",\n top: 0,\n left: 0,\n width: \"100%\",\n height: \"100%\",\n pointerEvents: \"none\",\n zIndex: Z_INDEX.HUD,\n overflow: \"clip\",\n }}\n >\n {/* Top HUD - Round info, timer, return to menu */}\n <CombatTopHUD\n width={width}\n height={height}\n isMobile={isMobile}\n positionScale={positionScale}\n currentRound={internalRound}\n totalRounds={3}\n timerState={timerState}\n showTimer={\n combatState.roundStarted &&\n !combatState.roundEnded &&\n matchCountdownComplete &&\n !showRoundStart\n }\n onReturnToMenu={onReturnToMenu}\n isPaused={isPaused || showPauseMenu}\n />\n\n {/* Left HUD - Player 1 stats.\n On mobile, side HUDs occlude the 3D arena in both portrait and\n landscape; collapse them away so the arena stays fully visible.\n Player status remains available via CombatPortraitStatusStrip and\n bottom combat controls. */}\n {!isMobile && (\n <CombatLeftHUD\n width={width}\n height={height}\n isMobile={isMobile}\n positionScale={positionScale}\n player={validPlayers[0]}\n laterality={combatState.playerLaterality[0]}\n isInGuard={player1Animation.isInStanceGuard()}\n speedModifiers={player1SpeedModifiers}\n />\n )}\n\n {/* Right HUD - Player 2/AI stats with difficulty indicator */}\n {!isMobile && (\n <CombatRightHUD\n width={width}\n height={height}\n isMobile={isMobile}\n positionScale={positionScale}\n player={validPlayers[1]}\n laterality={combatState.playerLaterality[1]}\n speedModifiers={player2SpeedModifiers}\n difficultyTier={currentDifficultyTier}\n />\n )}\n\n {/* Portrait-mobile HP/stamina strip. Replaces the hidden side HUDs\n so both players can still see their health at a glance without\n re-introducing arena occlusion. */}\n {isMobile && isPortrait && (\n <CombatPortraitStatusStrip\n width={width}\n height={height}\n player1={validPlayers[0]}\n player2={validPlayers[1]}\n positionScale={positionScale}\n topOffset={combatTopHudHeight}\n />\n )}\n\n {/* Bottom HUD - Technique bar, volume, messages */}\n <CombatBottomHUD\n width={width}\n height={height}\n isMobile={isMobile}\n positionScale={positionScale}\n visible={\n combatState.roundStarted &&\n !combatState.roundEnded &&\n matchCountdownComplete &&\n !showRoundStart\n }\n techniques={techniqueSelection.availableTechniques}\n player={validPlayers[0]}\n selectedIndex={techniqueSelection.selectedIndex}\n cooldowns={cooldownsMap}\n onTechniqueSelect={techniqueSelection.selectTechnique}\n combatMessages={combatState.combatMessages}\n />\n\n {/* Player State Visual Indicators */}\n {/* Player 1 State Overlay - includes consciousness blur, pain vignette, etc.\n In portrait mobile the arena is already rendered in a compressed 3:4\n aspect ratio, so halve the fullscreen vignette/blur/flash intensity\n to avoid further obscuring the scene. */}\n <PlayerStateOverlayHtml\n pain={validPlayers[0].pain}\n balanceState={getBalanceState(validPlayers[0].balance)}\n position=\"left\"\n consciousness={validPlayers[0].consciousness}\n bloodLoss={0} // FIXME: bloodLoss property not yet added to PlayerState interface - overlay will not display until implemented\n stamina={validPlayers[0].stamina}\n isMobile={isMobile}\n intensityScale={isMobile && isPortrait ? 0.5 : 1}\n />\n\n {/* Note: Player 2 (AI) does not get fullscreen state overlays like consciousness blur */}\n {/* as those effects would incorrectly affect the player's view */}\n\n {/* Breathing Disruption Indicators */}\n {/* Player 1 Breathing Indicator - positioned near left HUD */}\n <div\n style={{\n position: \"absolute\",\n left: isMobile ? \"10px\" : \"20px\",\n top: isMobile ? \"120px\" : \"160px\",\n zIndex: Z_INDEX.HUD + 1,\n pointerEvents: \"none\",\n }}\n data-testid=\"player1-breathing-indicator-container\"\n >\n <BreathingIndicator player={validPlayers[0]} isMobile={isMobile} />\n </div>\n\n {/* Player 2 Breathing Indicator - positioned near right HUD */}\n <div\n style={{\n position: \"absolute\",\n right: isMobile ? \"10px\" : \"20px\",\n top: isMobile ? \"120px\" : \"160px\",\n zIndex: Z_INDEX.HUD + 1,\n pointerEvents: \"none\",\n }}\n data-testid=\"player2-breathing-indicator-container\"\n >\n <BreathingIndicator player={validPlayers[1]} isMobile={isMobile} />\n </div>\n\n {/* Pause Menu Overlay */}\n {(isPaused || showPauseMenu) && (\n <PauseMenu\n onResume={handleResume}\n onRestart={handleRestart}\n onReturnToMenu={onReturnToMenu}\n isMobile={isMobile}\n />\n )}\n </div>\n\n {/* Round Announcement Overlay */}\n {showAnnouncement && roundWinner && (\n <RoundAnnouncement\n roundNumber={transitionRoundNumber}\n roundWinner={roundWinner}\n currentScore={matchScore}\n roundStats={{\n damageDealt: roundWinner.totalDamageDealt ?? 0,\n hitsLanded: roundWinner.hitsLanded ?? 0,\n vitalPointsHit: roundWinner.vitalPointHits ?? 0,\n accuracy: calculateAccuracy(roundWinner),\n }}\n onCountdownComplete={() => {\n if (matchScore.player1 >= 2 || matchScore.player2 >= 2) {\n const winner = matchScore.player1 >= 2 ? 0 : 1;\n onGameEnd(winner);\n } else {\n skipCountdown();\n }\n }}\n onSkip={() => {\n if (matchScore.player1 >= 2 || matchScore.player2 >= 2) {\n const winner = matchScore.player1 >= 2 ? 0 : 1;\n onGameEnd(winner);\n } else {\n skipCountdown();\n }\n }}\n isMobile={isMobile}\n totalRounds={3}\n />\n )}\n\n {/* Match Start Countdown Overlay - only shows once at match start */}\n {showMatchCountdown && !hasShownMatchCountdown && (\n <MatchCountdown\n onComplete={() => {\n setHasShownMatchCountdown(true);\n setShowMatchCountdown(false);\n setMatchCountdownComplete(true);\n startRound();\n }}\n isMobile={isMobile}\n showSkip={false}\n />\n )}\n\n {/* Round Start Announcement for subsequent rounds */}\n {/* Note: showRoundStart is only set to true after round 1 ends, so no need for internalRound > 1 check */}\n {showRoundStart && (\n <RoundStartAnnouncement\n roundNumber={internalRound}\n duration={2}\n onComplete={() => {\n if (import.meta.env.DEV) {\n console.log(\n \"[DEV] Round start announcement complete for round\",\n internalRound,\n );\n }\n setShowRoundStart(false);\n startRound();\n }}\n isMobile={isMobile}\n />\n )}\n\n {/* Round Display Status - Brief status messages */}\n {contentReady && combatState.roundDisplayStatus && (\n <RoundDisplayStatus\n status={combatState.roundDisplayStatus}\n isMobile={isMobile}\n />\n )}\n\n {/* Mobile Controls - Pure DOM, rendered OUTSIDE Canvas for reliable touch events */}\n {/* Uses pure DOM handlers instead of drei's Html which can block touch events on mobile */}\n {isMobile && (\n <>\n <MobileControlsOverlay\n onMove={handleMobileMove}\n onAttack={handleMobileAttack}\n onBlock={handleMobileBlock}\n bottom={getMobileControlsBottom(height)}\n viewportWidth={width}\n viewportHeight={height}\n />\n\n <StanceWheelPure\n currentStance={currentStanceIndex}\n onStanceChange={handleMobileStanceChange}\n expanded={stanceWheelExpanded}\n onToggle={toggleStanceWheel}\n disabled={!mobileControlsEnabled}\n opacity={0.8}\n />\n\n <GestureRecognizerPure\n onGesture={handleMobileGesture}\n enabled={mobileControlsEnabled}\n showFeedback={true}\n minSwipeDistance={50}\n />\n </>\n )}\n </div>\n );\n};\n\nexport default CombatScreen3D;\n"],"mappings":"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"}