blacktrigram 0.7.43 → 0.7.45

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 (750) hide show
  1. package/lib/audio/AudioManager.d.ts +26 -0
  2. package/lib/audio/AudioManager.d.ts.map +1 -1
  3. package/lib/audio/AudioManager.js +26 -0
  4. package/lib/audio/AudioManager.js.map +1 -1
  5. package/lib/audio/AudioPool.js +3 -0
  6. package/lib/audio/AudioPool.js.map +1 -1
  7. package/lib/audio/index.d.ts.map +1 -1
  8. package/lib/audio/index.js.map +1 -1
  9. package/lib/audio/types.d.ts +18 -2
  10. package/lib/audio/types.d.ts.map +1 -1
  11. package/lib/audio/types.js +1 -0
  12. package/lib/audio/types.js.map +1 -1
  13. package/lib/components/effects/WindParticles3D.d.ts.map +1 -1
  14. package/lib/components/index.d.ts.map +1 -1
  15. package/lib/components/index.js.map +1 -1
  16. package/lib/components/screens/combat/CombatScreen3D.d.ts.map +1 -1
  17. package/lib/components/screens/combat/CombatScreen3D.js.map +1 -1
  18. package/lib/components/screens/combat/components/controls/KeyboardHints.d.ts +0 -1
  19. package/lib/components/screens/combat/components/controls/KeyboardHints.d.ts.map +1 -1
  20. package/lib/components/screens/combat/components/controls/KeyboardHints.js +0 -1
  21. package/lib/components/screens/combat/components/controls/KeyboardHints.js.map +1 -1
  22. package/lib/components/screens/combat/components/controls/PauseMenu.d.ts.map +1 -1
  23. package/lib/components/screens/combat/components/controls/PauseMenu.js.map +1 -1
  24. package/lib/components/screens/combat/components/effects/ArterialSpray3D.d.ts.map +1 -1
  25. package/lib/components/screens/combat/components/effects/BloodDecals3D.d.ts.map +1 -1
  26. package/lib/components/screens/combat/components/effects/BloodDecals3D.js.map +1 -1
  27. package/lib/components/screens/combat/components/effects/BloodLossOverlayHtml.d.ts.map +1 -1
  28. package/lib/components/screens/combat/components/effects/BloodLossOverlayHtml.js.map +1 -1
  29. package/lib/components/screens/combat/components/effects/BloodParticles3D.d.ts.map +1 -1
  30. package/lib/components/screens/combat/components/effects/BloodParticles3D.js.map +1 -1
  31. package/lib/components/screens/combat/components/effects/BloodViscosity3D.d.ts.map +1 -1
  32. package/lib/components/screens/combat/components/effects/BloodViscosity3D.js.map +1 -1
  33. package/lib/components/screens/combat/components/effects/BoneCrackParticles3D.d.ts.map +1 -1
  34. package/lib/components/screens/combat/components/effects/CombatParticleEffects3D.d.ts.map +1 -1
  35. package/lib/components/screens/combat/components/effects/CombatParticleEffects3D.js.map +1 -1
  36. package/lib/components/screens/combat/components/effects/ConsciousnessBlur.d.ts.map +1 -1
  37. package/lib/components/screens/combat/components/effects/ConsciousnessBlur.js.map +1 -1
  38. package/lib/components/screens/combat/components/effects/DustClouds3D.d.ts.map +1 -1
  39. package/lib/components/screens/combat/components/effects/EarthCrackEffect3D.d.ts.map +1 -1
  40. package/lib/components/screens/combat/components/effects/EarthHealingEffect3D.d.ts.map +1 -1
  41. package/lib/components/screens/combat/components/effects/ImpactSparks3D.d.ts.map +1 -1
  42. package/lib/components/screens/combat/components/effects/InternalDamage3D.d.ts.map +1 -1
  43. package/lib/components/screens/combat/components/effects/InternalDamage3D.js.map +1 -1
  44. package/lib/components/screens/combat/components/effects/LiPrecisionTargetingOverlay.d.ts.map +1 -1
  45. package/lib/components/screens/combat/components/effects/NerveStrikeParticles3D.d.ts.map +1 -1
  46. package/lib/components/screens/combat/components/effects/PainVignette.d.ts.map +1 -1
  47. package/lib/components/screens/combat/components/effects/PainVignette.js.map +1 -1
  48. package/lib/components/screens/combat/components/effects/ParticleAudio3D.d.ts.map +1 -1
  49. package/lib/components/screens/combat/components/effects/ParticleAudio3D.js.map +1 -1
  50. package/lib/components/screens/combat/components/effects/TraumaOverlay3D.d.ts.map +1 -1
  51. package/lib/components/screens/combat/components/effects/TraumaOverlay3D.js.map +1 -1
  52. package/lib/components/screens/combat/components/effects/WaterRipple3D.d.ts.map +1 -1
  53. package/lib/components/screens/combat/components/effects/WaterWave3D.d.ts.map +1 -1
  54. package/lib/components/screens/combat/components/effects/index.d.ts.map +1 -1
  55. package/lib/components/screens/combat/components/feedback/MatchCountdown.d.ts.map +1 -1
  56. package/lib/components/screens/combat/components/feedback/MatchCountdown.js.map +1 -1
  57. package/lib/components/screens/combat/components/feedback/RoundAnnouncementOverlayHtml.d.ts.map +1 -1
  58. package/lib/components/screens/combat/components/feedback/RoundAnnouncementOverlayHtml.js.map +1 -1
  59. package/lib/components/screens/combat/components/feedback/RoundStartAnnouncementOverlayHtml.d.ts.map +1 -1
  60. package/lib/components/screens/combat/components/feedback/RoundStartAnnouncementOverlayHtml.js.map +1 -1
  61. package/lib/components/screens/combat/components/hud/CombatBottomHUD.d.ts.map +1 -1
  62. package/lib/components/screens/combat/components/hud/CombatBottomHUD.js.map +1 -1
  63. package/lib/components/screens/combat/components/hud/CombatLeftHUD.d.ts.map +1 -1
  64. package/lib/components/screens/combat/components/hud/CombatLeftHUD.js.map +1 -1
  65. package/lib/components/screens/combat/components/hud/CombatPortraitStatusStrip.d.ts.map +1 -1
  66. package/lib/components/screens/combat/components/hud/CombatPortraitStatusStrip.js.map +1 -1
  67. package/lib/components/screens/combat/components/hud/CombatRightHUD.d.ts.map +1 -1
  68. package/lib/components/screens/combat/components/hud/CombatRightHUD.js.map +1 -1
  69. package/lib/components/screens/combat/components/hud/CombatTopHUD.d.ts.map +1 -1
  70. package/lib/components/screens/combat/components/hud/CombatTopHUD.js.map +1 -1
  71. package/lib/components/screens/combat/components/hud/DifficultyIndicator.d.ts.map +1 -1
  72. package/lib/components/screens/combat/components/hud/DifficultyIndicator.js.map +1 -1
  73. package/lib/components/screens/combat/components/hud/FPSMonitor.d.ts.map +1 -1
  74. package/lib/components/screens/combat/components/hud/FPSMonitor.js.map +1 -1
  75. package/lib/components/screens/combat/components/hud/PlayerStateOverlayHtml.d.ts.map +1 -1
  76. package/lib/components/screens/combat/components/hud/PlayerStateOverlayHtml.js.map +1 -1
  77. package/lib/components/screens/combat/components/indicators/BalanceIndicator.d.ts.map +1 -1
  78. package/lib/components/screens/combat/components/indicators/BalanceIndicator.js.map +1 -1
  79. package/lib/components/screens/combat/components/indicators/InputBufferDisplay.d.ts +0 -1
  80. package/lib/components/screens/combat/components/indicators/InputBufferDisplay.d.ts.map +1 -1
  81. package/lib/components/screens/combat/components/indicators/InputBufferDisplay.js +0 -1
  82. package/lib/components/screens/combat/components/indicators/InputBufferDisplay.js.map +1 -1
  83. package/lib/components/screens/combat/components/indicators/StaminaWarning.d.ts.map +1 -1
  84. package/lib/components/screens/combat/components/indicators/StaminaWarning.js.map +1 -1
  85. package/lib/components/screens/combat/components/indicators/TechniqueNameDisplay.d.ts +0 -2
  86. package/lib/components/screens/combat/components/indicators/TechniqueNameDisplay.d.ts.map +1 -1
  87. package/lib/components/screens/combat/components/indicators/TechniqueNameDisplay.js +0 -1
  88. package/lib/components/screens/combat/components/indicators/TechniqueNameDisplay.js.map +1 -1
  89. package/lib/components/screens/combat/helpers/AnimationUpdater.d.ts.map +1 -1
  90. package/lib/components/screens/combat/helpers/AnimationUpdater.js.map +1 -1
  91. package/lib/components/screens/combat/helpers/combatHelpers.d.ts.map +1 -1
  92. package/lib/components/screens/combat/helpers/combatHelpers.js.map +1 -1
  93. package/lib/components/screens/combat/hooks/useAICombat.d.ts.map +1 -1
  94. package/lib/components/screens/combat/hooks/useAICombat.js.map +1 -1
  95. package/lib/components/screens/combat/hooks/useCombatActions.d.ts.map +1 -1
  96. package/lib/components/screens/combat/hooks/useCombatActions.js.map +1 -1
  97. package/lib/components/screens/combat/hooks/useCombatAttackMovement.d.ts.map +1 -1
  98. package/lib/components/screens/combat/hooks/useCombatAttackMovement.js.map +1 -1
  99. package/lib/components/screens/combat/hooks/useCombatAudio.d.ts.map +1 -1
  100. package/lib/components/screens/combat/hooks/useCombatAudio.js.map +1 -1
  101. package/lib/components/screens/combat/hooks/useCombatLayout.d.ts.map +1 -1
  102. package/lib/components/screens/combat/hooks/useCombatLayout.js.map +1 -1
  103. package/lib/components/screens/combat/hooks/useCombatState.d.ts.map +1 -1
  104. package/lib/components/screens/combat/hooks/useCombatState.js.map +1 -1
  105. package/lib/components/screens/combat/hooks/useGrapplingAudio.d.ts.map +1 -1
  106. package/lib/components/screens/combat/hooks/usePreloadCombatAudio.d.ts.map +1 -1
  107. package/lib/components/screens/controls/ControlsScreen3D.d.ts.map +1 -1
  108. package/lib/components/screens/controls/ControlsScreen3D.js.map +1 -1
  109. package/lib/components/screens/controls/components/ControlBindingsOverlayHtml.d.ts.map +1 -1
  110. package/lib/components/screens/controls/components/ControlBindingsOverlayHtml.js.map +1 -1
  111. package/lib/components/screens/controls/components/GamepadVisualization3D.d.ts.map +1 -1
  112. package/lib/components/screens/controls/components/GamepadVisualization3D.js.map +1 -1
  113. package/lib/components/screens/controls/components/InteractiveControlDemoOverlayHtml.d.ts.map +1 -1
  114. package/lib/components/screens/controls/components/InteractiveControlDemoOverlayHtml.js.map +1 -1
  115. package/lib/components/screens/controls/components/Key3D.d.ts.map +1 -1
  116. package/lib/components/screens/controls/components/Key3D.js.map +1 -1
  117. package/lib/components/screens/controls/components/VisualKeyboard3D.d.ts.map +1 -1
  118. package/lib/components/screens/controls/components/VisualKeyboard3D.js.map +1 -1
  119. package/lib/components/screens/controls/constants/ControlsConstants.d.ts.map +1 -1
  120. package/lib/components/screens/controls/constants/ControlsConstants.js.map +1 -1
  121. package/lib/components/screens/controls/hooks/useControlsState.d.ts.map +1 -1
  122. package/lib/components/screens/controls/hooks/useControlsState.js.map +1 -1
  123. package/lib/components/screens/endscreen/EndScreen3D.d.ts.map +1 -1
  124. package/lib/components/screens/endscreen/EndScreen3D.js.map +1 -1
  125. package/lib/components/screens/endscreen/components/DefeatAnimation3D.d.ts.map +1 -1
  126. package/lib/components/screens/endscreen/components/DefeatAnimation3D.js.map +1 -1
  127. package/lib/components/screens/endscreen/components/NavigationButtonsOverlayHtml.d.ts.map +1 -1
  128. package/lib/components/screens/endscreen/components/NavigationButtonsOverlayHtml.js.map +1 -1
  129. package/lib/components/screens/endscreen/components/PerformanceBreakdownOverlayHtml.d.ts.map +1 -1
  130. package/lib/components/screens/endscreen/components/PerformanceBreakdownOverlayHtml.js.map +1 -1
  131. package/lib/components/screens/endscreen/components/PerformanceRatingOverlayHtml.d.ts.map +1 -1
  132. package/lib/components/screens/endscreen/components/PerformanceRatingOverlayHtml.js.map +1 -1
  133. package/lib/components/screens/endscreen/components/VictoryAnimation3D.d.ts.map +1 -1
  134. package/lib/components/screens/endscreen/components/VictoryAnimation3D.js.map +1 -1
  135. package/lib/components/screens/endscreen/components/WinnerDisplayOverlayHtml.d.ts.map +1 -1
  136. package/lib/components/screens/endscreen/components/WinnerDisplayOverlayHtml.js.map +1 -1
  137. package/lib/components/screens/endscreen/components/index.d.ts.map +1 -1
  138. package/lib/components/screens/endscreen/index.d.ts.map +1 -1
  139. package/lib/components/screens/intro/IntroScreen3D.d.ts.map +1 -1
  140. package/lib/components/screens/intro/IntroScreen3D.js +1 -1
  141. package/lib/components/screens/intro/IntroScreen3D.js.map +1 -1
  142. package/lib/components/screens/intro/components/AbilityListOverlayHtml.d.ts.map +1 -1
  143. package/lib/components/screens/intro/components/AbilityListOverlayHtml.js.map +1 -1
  144. package/lib/components/screens/intro/components/ArchetypeCardGridOverlayHtml.d.ts.map +1 -1
  145. package/lib/components/screens/intro/components/ArchetypeCardGridOverlayHtml.js.map +1 -1
  146. package/lib/components/screens/intro/components/ArchetypeCardOverlayHtml.d.ts.map +1 -1
  147. package/lib/components/screens/intro/components/ArchetypeCardOverlayHtml.js.map +1 -1
  148. package/lib/components/screens/intro/components/ArchetypeDisplayOverlayHtml.d.ts.map +1 -1
  149. package/lib/components/screens/intro/components/ArchetypeDisplayOverlayHtml.js.map +1 -1
  150. package/lib/components/screens/intro/components/EnhancedArchetypeDisplayOverlayHtml.d.ts.map +1 -1
  151. package/lib/components/screens/intro/components/EnhancedArchetypeDisplayOverlayHtml.js.map +1 -1
  152. package/lib/components/screens/intro/components/MenuButtonsOverlayHtml.d.ts.map +1 -1
  153. package/lib/components/screens/intro/components/MenuButtonsOverlayHtml.js.map +1 -1
  154. package/lib/components/screens/intro/components/MenuSectionOverlayHtml.d.ts.map +1 -1
  155. package/lib/components/screens/intro/components/MenuSectionOverlayHtml.js.map +1 -1
  156. package/lib/components/screens/intro/components/StatBarOverlayHtml.d.ts.map +1 -1
  157. package/lib/components/screens/intro/components/StatBarOverlayHtml.js.map +1 -1
  158. package/lib/components/screens/philosophy/PhilosophyScreen3D.d.ts.map +1 -1
  159. package/lib/components/screens/philosophy/PhilosophyScreen3D.js.map +1 -1
  160. package/lib/components/screens/philosophy/components/InteractiveTrigramGridOverlayHtml.d.ts +0 -1
  161. package/lib/components/screens/philosophy/components/InteractiveTrigramGridOverlayHtml.d.ts.map +1 -1
  162. package/lib/components/screens/philosophy/components/PhilosophyNavigationOverlayHtml.d.ts +0 -1
  163. package/lib/components/screens/philosophy/components/PhilosophyNavigationOverlayHtml.d.ts.map +1 -1
  164. package/lib/components/screens/philosophy/components/PhilosophySectionOverlayHtml.d.ts +0 -1
  165. package/lib/components/screens/philosophy/components/PhilosophySectionOverlayHtml.d.ts.map +1 -1
  166. package/lib/components/screens/philosophy/components/PhilosophyTextOverlayHtml.d.ts +0 -1
  167. package/lib/components/screens/philosophy/components/PhilosophyTextOverlayHtml.d.ts.map +1 -1
  168. package/lib/components/screens/philosophy/components/TrigramSymbol3D.d.ts +0 -1
  169. package/lib/components/screens/philosophy/components/TrigramSymbol3D.d.ts.map +1 -1
  170. package/lib/components/screens/philosophy/components/TrigramVisualization3D.d.ts +0 -1
  171. package/lib/components/screens/philosophy/components/TrigramVisualization3D.d.ts.map +1 -1
  172. package/lib/components/screens/philosophy/hooks/usePhilosophyState.d.ts +0 -1
  173. package/lib/components/screens/philosophy/hooks/usePhilosophyState.d.ts.map +1 -1
  174. package/lib/components/screens/training/TrainingScreen3D.d.ts.map +1 -1
  175. package/lib/components/screens/training/TrainingScreen3D.js.map +1 -1
  176. package/lib/components/screens/training/components/AnatomyControlsOverlayHtml.d.ts.map +1 -1
  177. package/lib/components/screens/training/components/AnatomyControlsOverlayHtml.js.map +1 -1
  178. package/lib/components/screens/training/components/AnatomyOverlay3D.d.ts.map +1 -1
  179. package/lib/components/screens/training/components/AnatomyOverlay3D.js.map +1 -1
  180. package/lib/components/screens/training/components/DamageNumber3D.d.ts.map +1 -1
  181. package/lib/components/screens/training/components/FootPlacementMarkers3D.d.ts.map +1 -1
  182. package/lib/components/screens/training/components/FootPlacementMarkers3D.js.map +1 -1
  183. package/lib/components/screens/training/components/FootworkDrillsOverlayHtml.d.ts.map +1 -1
  184. package/lib/components/screens/training/components/FootworkDrillsOverlayHtml.js.map +1 -1
  185. package/lib/components/screens/training/components/HitFeedbackEffect3D.d.ts.map +1 -1
  186. package/lib/components/screens/training/components/HitFeedbackEffect3D.js.map +1 -1
  187. package/lib/components/screens/training/components/TrainingAICharacter3D.d.ts.map +1 -1
  188. package/lib/components/screens/training/components/TrainingArena3D.d.ts.map +1 -1
  189. package/lib/components/screens/training/components/TrainingControlsOverlayHtml.d.ts.map +1 -1
  190. package/lib/components/screens/training/components/TrainingControlsOverlayHtml.js.map +1 -1
  191. package/lib/components/screens/training/components/TrainingDummy3D.d.ts.map +1 -1
  192. package/lib/components/screens/training/components/TrainingDummy3D.js.map +1 -1
  193. package/lib/components/screens/training/components/TrainingFeedbackOverlayHtml.d.ts.map +1 -1
  194. package/lib/components/screens/training/components/TrainingFeedbackOverlayHtml.js.map +1 -1
  195. package/lib/components/screens/training/components/TrainingHitEffects3D.d.ts.map +1 -1
  196. package/lib/components/screens/training/components/TrainingModeSelectorOverlayHtml.d.ts.map +1 -1
  197. package/lib/components/screens/training/components/TrainingModeSelectorOverlayHtml.js.map +1 -1
  198. package/lib/components/screens/training/components/TrainingStatsOverlayHtml.d.ts.map +1 -1
  199. package/lib/components/screens/training/components/TrainingStatsOverlayHtml.js.map +1 -1
  200. package/lib/components/screens/training/components/VitalPointMarker3D.d.ts.map +1 -1
  201. package/lib/components/screens/training/components/VitalPointMarker3D.js.map +1 -1
  202. package/lib/components/screens/training/components/VitalPointTrainingOverlayHtml.d.ts.map +1 -1
  203. package/lib/components/screens/training/components/VitalPointTrainingOverlayHtml.js.map +1 -1
  204. package/lib/components/screens/training/components/hud/TrainingBottomHUD.d.ts.map +1 -1
  205. package/lib/components/screens/training/components/hud/TrainingBottomHUD.js.map +1 -1
  206. package/lib/components/screens/training/components/hud/TrainingLeftHUD.d.ts.map +1 -1
  207. package/lib/components/screens/training/components/hud/TrainingLeftHUD.js.map +1 -1
  208. package/lib/components/screens/training/components/hud/TrainingRightHUD.d.ts.map +1 -1
  209. package/lib/components/screens/training/components/hud/TrainingRightHUD.js.map +1 -1
  210. package/lib/components/screens/training/components/hud/TrainingTopHUD.d.ts.map +1 -1
  211. package/lib/components/screens/training/components/hud/TrainingTopHUD.js.map +1 -1
  212. package/lib/components/screens/training/components/index.d.ts.map +1 -1
  213. package/lib/components/screens/training/hooks/useAttackMovement.d.ts.map +1 -1
  214. package/lib/components/screens/training/hooks/useAttackMovement.js.map +1 -1
  215. package/lib/components/screens/training/hooks/useTrainingActions.d.ts.map +1 -1
  216. package/lib/components/screens/training/hooks/useTrainingActions.js.map +1 -1
  217. package/lib/components/screens/training/hooks/useTrainingLayout.d.ts.map +1 -1
  218. package/lib/components/screens/training/hooks/useTrainingLayout.js.map +1 -1
  219. package/lib/components/screens/training/hooks/useTrainingState.d.ts.map +1 -1
  220. package/lib/components/screens/training/hooks/useTrainingState.js.map +1 -1
  221. package/lib/components/shared/base/AccessibilityProvider.d.ts.map +1 -1
  222. package/lib/components/shared/base/BaseButton.d.ts.map +1 -1
  223. package/lib/components/shared/base/BaseButton.js.map +1 -1
  224. package/lib/components/shared/base/BaseButtonOverlayHtml.d.ts.map +1 -1
  225. package/lib/components/shared/base/BaseButtonOverlayHtml.js.map +1 -1
  226. package/lib/components/shared/base/BasePanel.d.ts.map +1 -1
  227. package/lib/components/shared/base/BasePanel.js.map +1 -1
  228. package/lib/components/shared/base/BaseText.d.ts.map +1 -1
  229. package/lib/components/shared/base/BaseText.js.map +1 -1
  230. package/lib/components/shared/base/ResponsiveContainer.d.ts.map +1 -1
  231. package/lib/components/shared/base/index.d.ts.map +1 -1
  232. package/lib/components/shared/base/useKoreanTheme.d.ts.map +1 -1
  233. package/lib/components/shared/base/useKoreanTheme.js.map +1 -1
  234. package/lib/components/shared/debug/PerformanceDebugOverlayHtml.d.ts.map +1 -1
  235. package/lib/components/shared/debug/PerformanceDebugOverlayHtml.js.map +1 -1
  236. package/lib/components/shared/effects/ScreenFlash.d.ts.map +1 -1
  237. package/lib/components/shared/mobile/ActionButtons.d.ts.map +1 -1
  238. package/lib/components/shared/mobile/ActionButtons.js +0 -1
  239. package/lib/components/shared/mobile/ActionButtons.js.map +1 -1
  240. package/lib/components/shared/mobile/GestureRecognizerPure.d.ts +0 -1
  241. package/lib/components/shared/mobile/GestureRecognizerPure.d.ts.map +1 -1
  242. package/lib/components/shared/mobile/GestureRecognizerPure.js +0 -1
  243. package/lib/components/shared/mobile/GestureRecognizerPure.js.map +1 -1
  244. package/lib/components/shared/mobile/HapticController.d.ts +0 -13
  245. package/lib/components/shared/mobile/HapticController.d.ts.map +1 -1
  246. package/lib/components/shared/mobile/HapticController.js +0 -10
  247. package/lib/components/shared/mobile/HapticController.js.map +1 -1
  248. package/lib/components/shared/mobile/MobileControlsPure.d.ts.map +1 -1
  249. package/lib/components/shared/mobile/MobileControlsPure.js.map +1 -1
  250. package/lib/components/shared/mobile/PerformanceMonitor.d.ts +0 -15
  251. package/lib/components/shared/mobile/PerformanceMonitor.d.ts.map +1 -1
  252. package/lib/components/shared/mobile/StanceWheelPure.d.ts +0 -1
  253. package/lib/components/shared/mobile/StanceWheelPure.d.ts.map +1 -1
  254. package/lib/components/shared/mobile/StanceWheelPure.js +0 -1
  255. package/lib/components/shared/mobile/StanceWheelPure.js.map +1 -1
  256. package/lib/components/shared/mobile/TouchOptimizer.d.ts +0 -4
  257. package/lib/components/shared/mobile/TouchOptimizer.d.ts.map +1 -1
  258. package/lib/components/shared/mobile/TouchOptimizer.js +0 -3
  259. package/lib/components/shared/mobile/TouchOptimizer.js.map +1 -1
  260. package/lib/components/shared/mobile/VirtualDPad.d.ts.map +1 -1
  261. package/lib/components/shared/mobile/VirtualDPad.js +0 -1
  262. package/lib/components/shared/mobile/VirtualDPad.js.map +1 -1
  263. package/lib/components/shared/mobile/index.d.ts.map +1 -1
  264. package/lib/components/shared/three/anatomy/BodySurface.d.ts.map +1 -1
  265. package/lib/components/shared/three/anatomy/BodySurface.js.map +1 -1
  266. package/lib/components/shared/three/anatomy/BoneAttachedMuscles.d.ts.map +1 -1
  267. package/lib/components/shared/three/anatomy/BoneAttachedMuscles.js.map +1 -1
  268. package/lib/components/shared/three/anatomy/BoneClothing.d.ts.map +1 -1
  269. package/lib/components/shared/three/anatomy/BoneClothing.js.map +1 -1
  270. package/lib/components/shared/three/anatomy/BoneRenderer.d.ts +0 -1
  271. package/lib/components/shared/three/anatomy/BoneRenderer.d.ts.map +1 -1
  272. package/lib/components/shared/three/anatomy/BoneRenderer.js.map +1 -1
  273. package/lib/components/shared/three/anatomy/Face3D.d.ts.map +1 -1
  274. package/lib/components/shared/three/anatomy/Face3D.js.map +1 -1
  275. package/lib/components/shared/three/anatomy/Foot3D.d.ts +0 -1
  276. package/lib/components/shared/three/anatomy/Foot3D.d.ts.map +1 -1
  277. package/lib/components/shared/three/anatomy/Foot3D.js.map +1 -1
  278. package/lib/components/shared/three/anatomy/Hand3D.d.ts +0 -1
  279. package/lib/components/shared/three/anatomy/Hand3D.d.ts.map +1 -1
  280. package/lib/components/shared/three/anatomy/Hand3D.js.map +1 -1
  281. package/lib/components/shared/three/effects/ActionFeedback.d.ts.map +1 -1
  282. package/lib/components/shared/three/effects/ActionFeedback.js.map +1 -1
  283. package/lib/components/shared/three/effects/DamageNumbers.d.ts.map +1 -1
  284. package/lib/components/shared/three/effects/DamageNumbers.js.map +1 -1
  285. package/lib/components/shared/three/effects/ExplosiveBurstEffect3D.d.ts.map +1 -1
  286. package/lib/components/shared/three/effects/GrapplingIndicator3D.d.ts.map +1 -1
  287. package/lib/components/shared/three/effects/HitEffects3D.d.ts.map +1 -1
  288. package/lib/components/shared/three/effects/HitEffects3D.js.map +1 -1
  289. package/lib/components/shared/three/effects/LimbExposureIndicator3D.d.ts.map +1 -1
  290. package/lib/components/shared/three/effects/NerveDisruptionEffect3D.d.ts.map +1 -1
  291. package/lib/components/shared/three/effects/PlayerStateIndicators.d.ts.map +1 -1
  292. package/lib/components/shared/three/effects/PlayerStateIndicators.js.map +1 -1
  293. package/lib/components/shared/three/effects/StanceSymbol3D.d.ts.map +1 -1
  294. package/lib/components/shared/three/effects/StanceSymbol3D.js.map +1 -1
  295. package/lib/components/shared/three/effects/StanceTransitionEffect.d.ts.map +1 -1
  296. package/lib/components/shared/three/effects/StanceTransitionEffect.js.map +1 -1
  297. package/lib/components/shared/three/effects/ThunderEffect3D.d.ts.map +1 -1
  298. package/lib/components/shared/three/effects/VitalPointMarkers3D.d.ts.map +1 -1
  299. package/lib/components/shared/three/effects/VitalPointMarkers3D.js.map +1 -1
  300. package/lib/components/shared/three/index.d.ts.map +1 -1
  301. package/lib/components/shared/three/indicators/ElementalColorSystem.d.ts +0 -6
  302. package/lib/components/shared/three/indicators/ElementalColorSystem.d.ts.map +1 -1
  303. package/lib/components/shared/three/indicators/ElementalColorSystem.js +0 -4
  304. package/lib/components/shared/three/indicators/ElementalColorSystem.js.map +1 -1
  305. package/lib/components/shared/three/indicators/GuardIndicator.d.ts +0 -1
  306. package/lib/components/shared/three/indicators/GuardIndicator.d.ts.map +1 -1
  307. package/lib/components/shared/three/indicators/GuardIndicator.js +0 -1
  308. package/lib/components/shared/three/indicators/GuardIndicator.js.map +1 -1
  309. package/lib/components/shared/three/indicators/HapticFeedback.d.ts +0 -7
  310. package/lib/components/shared/three/indicators/HapticFeedback.d.ts.map +1 -1
  311. package/lib/components/shared/three/indicators/HapticFeedback.js +0 -2
  312. package/lib/components/shared/three/indicators/HapticFeedback.js.map +1 -1
  313. package/lib/components/shared/three/indicators/StanceChangeIndicator.d.ts +0 -1
  314. package/lib/components/shared/three/indicators/StanceChangeIndicator.d.ts.map +1 -1
  315. package/lib/components/shared/three/indicators/StanceChangeIndicator.js +0 -1
  316. package/lib/components/shared/three/indicators/StanceChangeIndicator.js.map +1 -1
  317. package/lib/components/shared/three/indicators/TrigramSymbol3D.d.ts +0 -1
  318. package/lib/components/shared/three/indicators/TrigramSymbol3D.d.ts.map +1 -1
  319. package/lib/components/shared/three/models/Player3DWithTransitions.d.ts.map +1 -1
  320. package/lib/components/shared/three/models/Player3DWithTransitions.js.map +1 -1
  321. package/lib/components/shared/three/models/SkeletalPlayer3D.d.ts.map +1 -1
  322. package/lib/components/shared/three/models/SkeletalPlayer3D.js.map +1 -1
  323. package/lib/components/shared/three/optimization/AdaptiveQuality.d.ts.map +1 -1
  324. package/lib/components/shared/three/optimization/AdaptiveQuality.js.map +1 -1
  325. package/lib/components/shared/three/optimization/InstancedGeometry.d.ts.map +1 -1
  326. package/lib/components/shared/three/optimization/LODSystem.d.ts.map +1 -1
  327. package/lib/components/shared/three/scene/AtmosphericParticles3D.d.ts.map +1 -1
  328. package/lib/components/shared/three/scene/AtmosphericParticles3D.js.map +1 -1
  329. package/lib/components/shared/three/scene/BackgroundScene3D.d.ts.map +1 -1
  330. package/lib/components/shared/three/scene/BackgroundScene3D.js.map +1 -1
  331. package/lib/components/shared/three/scene/CombatArena3D.d.ts.map +1 -1
  332. package/lib/components/shared/three/scene/CombatArena3D.js.map +1 -1
  333. package/lib/components/shared/three/scene/DebugCollision.d.ts +0 -2
  334. package/lib/components/shared/three/scene/DebugCollision.d.ts.map +1 -1
  335. package/lib/components/shared/three/scene/KoreanSignage3D.d.ts.map +1 -1
  336. package/lib/components/shared/three/scene/KoreanSignage3D.js.map +1 -1
  337. package/lib/components/shared/three/ui/ArchetypeCard.d.ts.map +1 -1
  338. package/lib/components/shared/three/ui/ArchetypeCard.js.map +1 -1
  339. package/lib/components/shared/three/ui/BodyPartHealthDisplay.d.ts.map +1 -1
  340. package/lib/components/shared/three/ui/BodyPartHealthDisplay.js.map +1 -1
  341. package/lib/components/shared/three/ui/BreathingIndicator.d.ts.map +1 -1
  342. package/lib/components/shared/three/ui/BreathingIndicator2.js.map +1 -1
  343. package/lib/components/shared/three/ui/CombatReadinessBar.d.ts.map +1 -1
  344. package/lib/components/shared/three/ui/CombatReadinessBar.js.map +1 -1
  345. package/lib/components/shared/three/ui/ComboCounter.d.ts.map +1 -1
  346. package/lib/components/shared/three/ui/ComboCounter.js.map +1 -1
  347. package/lib/components/shared/three/ui/HealthBar.d.ts.map +1 -1
  348. package/lib/components/shared/three/ui/HealthBar.js.map +1 -1
  349. package/lib/components/shared/three/ui/KoreanButton.d.ts.map +1 -1
  350. package/lib/components/shared/three/ui/KoreanButton.js.map +1 -1
  351. package/lib/components/shared/three/ui/KoreanPanel.d.ts.map +1 -1
  352. package/lib/components/shared/three/ui/KoreanPanel.js.map +1 -1
  353. package/lib/components/shared/three/ui/KoreanText.d.ts.map +1 -1
  354. package/lib/components/shared/three/ui/KoreanText.js.map +1 -1
  355. package/lib/components/shared/three/ui/MenuList.d.ts.map +1 -1
  356. package/lib/components/shared/three/ui/MenuList.js.map +1 -1
  357. package/lib/components/shared/three/ui/PlayerHUD.d.ts.map +1 -1
  358. package/lib/components/shared/three/ui/PlayerHUD.js.map +1 -1
  359. package/lib/components/shared/three/ui/ProgressBar.d.ts.map +1 -1
  360. package/lib/components/shared/three/ui/ProgressBar.js.map +1 -1
  361. package/lib/components/shared/three/ui/SpeedIndicatorHUD.d.ts +0 -1
  362. package/lib/components/shared/three/ui/SpeedIndicatorHUD.d.ts.map +1 -1
  363. package/lib/components/shared/three/ui/SpeedIndicatorHUD.js +0 -1
  364. package/lib/components/shared/three/ui/SpeedIndicatorHUD.js.map +1 -1
  365. package/lib/components/shared/three/ui/StaminaBar.d.ts.map +1 -1
  366. package/lib/components/shared/three/ui/StaminaBar.js.map +1 -1
  367. package/lib/components/shared/three/ui/TechniqueBar.d.ts.map +1 -1
  368. package/lib/components/shared/three/ui/TechniqueBar.js.map +1 -1
  369. package/lib/components/shared/three/ui/TechniqueBarContainer.d.ts.map +1 -1
  370. package/lib/components/shared/three/ui/TechniqueCard.d.ts.map +1 -1
  371. package/lib/components/shared/three/ui/TechniqueCard.js.map +1 -1
  372. package/lib/components/shared/three/ui/VitalPointOverlayControlsHtml.d.ts.map +1 -1
  373. package/lib/components/shared/three/ui/VitalPointOverlayControlsHtml.js.map +1 -1
  374. package/lib/components/shared/three/ui/VulnerabilityWindowHUD.d.ts.map +1 -1
  375. package/lib/components/shared/ui/BaseHUDContainer.d.ts.map +1 -1
  376. package/lib/components/shared/ui/BaseHUDContainer.js.map +1 -1
  377. package/lib/components/shared/ui/CombatTimer.d.ts.map +1 -1
  378. package/lib/components/shared/ui/CombatTimer.js.map +1 -1
  379. package/lib/components/shared/ui/ErrorBoundary.d.ts.map +1 -1
  380. package/lib/components/shared/ui/ErrorModal.d.ts.map +1 -1
  381. package/lib/components/shared/ui/ErrorModal.js.map +1 -1
  382. package/lib/components/shared/ui/HUDSection.d.ts.map +1 -1
  383. package/lib/components/shared/ui/LoadingState.d.ts.map +1 -1
  384. package/lib/components/shared/ui/LoadingState.js.map +1 -1
  385. package/lib/components/shared/ui/MobileHUDLayout.d.ts +0 -1
  386. package/lib/components/shared/ui/MobileHUDLayout.d.ts.map +1 -1
  387. package/lib/components/shared/ui/ResponsiveContainer.d.ts +0 -1
  388. package/lib/components/shared/ui/ResponsiveContainer.d.ts.map +1 -1
  389. package/lib/components/shared/ui/SplashScreen.d.ts.map +1 -1
  390. package/lib/components/shared/ui/SplashScreen.js +2 -2
  391. package/lib/components/shared/ui/SplashScreen.js.map +1 -1
  392. package/lib/components/shared/ui/StyledHUDPanel.d.ts.map +1 -1
  393. package/lib/components/shared/ui/VitalPointOverlayControlsPure.d.ts.map +1 -1
  394. package/lib/components/shared/ui/VitalPointOverlayControlsPure.js.map +1 -1
  395. package/lib/components/shared/ui/VolumeControl.d.ts.map +1 -1
  396. package/lib/components/shared/ui/VolumeControl.js.map +1 -1
  397. package/lib/components/shared/ui/shared/ConfirmDialog.d.ts.map +1 -1
  398. package/lib/components/shared/ui/shared/ConfirmDialog.js.map +1 -1
  399. package/lib/components/test/Hello3D.d.ts.map +1 -1
  400. package/lib/components/ui/combat/BalanceIndicatorOverlayHtml.d.ts.map +1 -1
  401. package/lib/components/ui/combat/BalanceIndicatorOverlayHtml.js.map +1 -1
  402. package/lib/components/ui/combat/ComboCounter.d.ts.map +1 -1
  403. package/lib/components/ui/combat/PressureMeter.d.ts.map +1 -1
  404. package/lib/systems/CombatSystem.d.ts +0 -6
  405. package/lib/systems/CombatSystem.d.ts.map +1 -1
  406. package/lib/systems/CombatSystem.js +0 -6
  407. package/lib/systems/CombatSystem.js.map +1 -1
  408. package/lib/systems/EffectCalculator.d.ts +0 -7
  409. package/lib/systems/EffectCalculator.d.ts.map +1 -1
  410. package/lib/systems/EffectCalculator.js +0 -4
  411. package/lib/systems/EffectCalculator.js.map +1 -1
  412. package/lib/systems/LayoutSystem.d.ts +0 -1
  413. package/lib/systems/LayoutSystem.d.ts.map +1 -1
  414. package/lib/systems/LayoutSystem.js +0 -1
  415. package/lib/systems/LayoutSystem.js.map +1 -1
  416. package/lib/systems/PlayerEffectManager.d.ts +0 -10
  417. package/lib/systems/PlayerEffectManager.d.ts.map +1 -1
  418. package/lib/systems/PlayerEffectManager.js +0 -3
  419. package/lib/systems/PlayerEffectManager.js.map +1 -1
  420. package/lib/systems/ResponsiveScaling.d.ts +0 -12
  421. package/lib/systems/ResponsiveScaling.d.ts.map +1 -1
  422. package/lib/systems/ResponsiveScaling.js +0 -12
  423. package/lib/systems/ResponsiveScaling.js.map +1 -1
  424. package/lib/systems/TrigramSystem.d.ts +0 -13
  425. package/lib/systems/TrigramSystem.d.ts.map +1 -1
  426. package/lib/systems/TrigramSystem.js +0 -13
  427. package/lib/systems/TrigramSystem.js.map +1 -1
  428. package/lib/systems/VitalPointSystem.d.ts +0 -10
  429. package/lib/systems/VitalPointSystem.d.ts.map +1 -1
  430. package/lib/systems/VitalPointSystem.js +0 -10
  431. package/lib/systems/VitalPointSystem.js.map +1 -1
  432. package/lib/systems/animation/builders/KeyframeInterpolation.d.ts +0 -4
  433. package/lib/systems/animation/builders/KeyframeInterpolation.d.ts.map +1 -1
  434. package/lib/systems/animation/builders/KeyframeInterpolation.js +0 -1
  435. package/lib/systems/animation/builders/KeyframeInterpolation.js.map +1 -1
  436. package/lib/systems/animation/builders/SkeletonRig.d.ts +0 -4
  437. package/lib/systems/animation/builders/SkeletonRig.d.ts.map +1 -1
  438. package/lib/systems/animation/builders/SkeletonRig.js +0 -3
  439. package/lib/systems/animation/builders/SkeletonRig.js.map +1 -1
  440. package/lib/systems/animation/catalogs/RecoveryAnimations.d.ts +0 -5
  441. package/lib/systems/animation/catalogs/RecoveryAnimations.d.ts.map +1 -1
  442. package/lib/systems/animation/catalogs/RecoveryAnimations.js +0 -5
  443. package/lib/systems/animation/catalogs/RecoveryAnimations.js.map +1 -1
  444. package/lib/systems/animation/core/AnimationHitTiming.d.ts +0 -6
  445. package/lib/systems/animation/core/AnimationHitTiming.d.ts.map +1 -1
  446. package/lib/systems/animation/core/AnimationHitTiming.js +0 -4
  447. package/lib/systems/animation/core/AnimationHitTiming.js.map +1 -1
  448. package/lib/systems/animation/core/AnimationStateMachine.js +1 -0
  449. package/lib/systems/animation/core/AnimationStateMachine.js.map +1 -1
  450. package/lib/systems/animation/core/AnimationTransitions.d.ts +0 -3
  451. package/lib/systems/animation/core/AnimationTransitions.d.ts.map +1 -1
  452. package/lib/systems/animation/core/AnimationTransitions.js.map +1 -1
  453. package/lib/systems/animation/core/LateralityTransform.d.ts +0 -3
  454. package/lib/systems/animation/core/LateralityTransform.d.ts.map +1 -1
  455. package/lib/systems/animation/core/LateralityTransform.js +0 -1
  456. package/lib/systems/animation/core/LateralityTransform.js.map +1 -1
  457. package/lib/systems/animation/core/RecoveryPhaseEnhancer.d.ts +0 -1
  458. package/lib/systems/animation/core/RecoveryPhaseEnhancer.d.ts.map +1 -1
  459. package/lib/systems/animation/core/RecoveryPhaseEnhancer.js.map +1 -1
  460. package/lib/systems/animation/core/TechniqueAnimationMapper.d.ts +0 -10
  461. package/lib/systems/animation/core/TechniqueAnimationMapper.d.ts.map +1 -1
  462. package/lib/systems/animation/core/TechniqueAnimationMapper.js +0 -8
  463. package/lib/systems/animation/core/TechniqueAnimationMapper.js.map +1 -1
  464. package/lib/systems/animation/core/TrigramAnimationMapping.d.ts +0 -10
  465. package/lib/systems/animation/core/TrigramAnimationMapping.d.ts.map +1 -1
  466. package/lib/systems/animation/core/TrigramStanceTransitions.d.ts +0 -2
  467. package/lib/systems/animation/core/TrigramStanceTransitions.d.ts.map +1 -1
  468. package/lib/systems/animation/core/types.d.ts +0 -39
  469. package/lib/systems/animation/core/types.d.ts.map +1 -1
  470. package/lib/systems/animation/core/types.js +0 -9
  471. package/lib/systems/animation/core/types.js.map +1 -1
  472. package/lib/systems/animation/systems/AdvancedJointMovements.d.ts +0 -27
  473. package/lib/systems/animation/systems/AdvancedJointMovements.d.ts.map +1 -1
  474. package/lib/systems/animation/systems/AdvancedJointMovements.js +0 -1
  475. package/lib/systems/animation/systems/AdvancedJointMovements.js.map +1 -1
  476. package/lib/systems/animation/systems/BodyFacingSystem.d.ts +0 -19
  477. package/lib/systems/animation/systems/BodyFacingSystem.d.ts.map +1 -1
  478. package/lib/systems/animation/systems/BodyFacingSystem.js +0 -14
  479. package/lib/systems/animation/systems/BodyFacingSystem.js.map +1 -1
  480. package/lib/systems/animation/systems/FacialExpressions.d.ts +0 -10
  481. package/lib/systems/animation/systems/FacialExpressions.d.ts.map +1 -1
  482. package/lib/systems/animation/systems/FacialExpressions.js +0 -2
  483. package/lib/systems/animation/systems/FacialExpressions.js.map +1 -1
  484. package/lib/systems/animation/systems/FallAnimations.d.ts +0 -4
  485. package/lib/systems/animation/systems/FallAnimations.d.ts.map +1 -1
  486. package/lib/systems/animation/systems/FallAnimations.js +0 -2
  487. package/lib/systems/animation/systems/FallAnimations.js.map +1 -1
  488. package/lib/systems/animation/systems/HeadMovements.d.ts +0 -10
  489. package/lib/systems/animation/systems/HeadMovements.d.ts.map +1 -1
  490. package/lib/systems/bodypart/BodyPartDamageIntegration.d.ts +0 -7
  491. package/lib/systems/bodypart/BodyPartDamageIntegration.d.ts.map +1 -1
  492. package/lib/systems/bodypart/BodyPartDamageIntegration.js +0 -7
  493. package/lib/systems/bodypart/BodyPartDamageIntegration.js.map +1 -1
  494. package/lib/systems/bodypart/BodyPartHealthSystem.d.ts +0 -13
  495. package/lib/systems/bodypart/BodyPartHealthSystem.d.ts.map +1 -1
  496. package/lib/systems/bodypart/BodyPartHealthSystem.js +0 -13
  497. package/lib/systems/bodypart/BodyPartHealthSystem.js.map +1 -1
  498. package/lib/systems/bodypart/BodyPartPositionMapping.d.ts +0 -6
  499. package/lib/systems/bodypart/BodyPartPositionMapping.d.ts.map +1 -1
  500. package/lib/systems/bodypart/BodyPartPositionMapping.js +0 -6
  501. package/lib/systems/bodypart/BodyPartPositionMapping.js.map +1 -1
  502. package/lib/systems/bodypart/CombatInjuryIntegration.d.ts +0 -10
  503. package/lib/systems/bodypart/CombatInjuryIntegration.d.ts.map +1 -1
  504. package/lib/systems/bodypart/CombatInjuryIntegration.js +0 -8
  505. package/lib/systems/bodypart/CombatInjuryIntegration.js.map +1 -1
  506. package/lib/systems/bodypart/InjuryIntegration.d.ts +0 -2
  507. package/lib/systems/bodypart/InjuryIntegration.d.ts.map +1 -1
  508. package/lib/systems/bodypart/InjuryIntegration.js +0 -2
  509. package/lib/systems/bodypart/InjuryIntegration.js.map +1 -1
  510. package/lib/systems/bodypart/InjuryTracker.d.ts +0 -14
  511. package/lib/systems/bodypart/InjuryTracker.d.ts.map +1 -1
  512. package/lib/systems/bodypart/InjuryTracker.js +0 -12
  513. package/lib/systems/bodypart/InjuryTracker.js.map +1 -1
  514. package/lib/systems/bodypart/MovementPenaltySystem.d.ts +0 -8
  515. package/lib/systems/bodypart/MovementPenaltySystem.d.ts.map +1 -1
  516. package/lib/systems/bodypart/MovementPenaltySystem.js +0 -8
  517. package/lib/systems/bodypart/MovementPenaltySystem.js.map +1 -1
  518. package/lib/systems/bodypart/PlayerInjuryTrackingManager.d.ts +0 -8
  519. package/lib/systems/bodypart/PlayerInjuryTrackingManager.d.ts.map +1 -1
  520. package/lib/systems/bodypart/PlayerInjuryTrackingManager.js +0 -8
  521. package/lib/systems/bodypart/PlayerInjuryTrackingManager.js.map +1 -1
  522. package/lib/systems/bodypart/types.d.ts +0 -13
  523. package/lib/systems/bodypart/types.d.ts.map +1 -1
  524. package/lib/systems/bodypart/types.js +0 -5
  525. package/lib/systems/bodypart/types.js.map +1 -1
  526. package/lib/systems/breathing/BreathingDisruptionSystem.d.ts +0 -3
  527. package/lib/systems/breathing/BreathingDisruptionSystem.d.ts.map +1 -1
  528. package/lib/systems/breathing/BreathingDisruptionSystem.js +0 -2
  529. package/lib/systems/breathing/BreathingDisruptionSystem.js.map +1 -1
  530. package/lib/systems/combat/BalanceSystem.d.ts +0 -25
  531. package/lib/systems/combat/BalanceSystem.d.ts.map +1 -1
  532. package/lib/systems/combat/BalanceSystem.js +0 -25
  533. package/lib/systems/combat/BalanceSystem.js.map +1 -1
  534. package/lib/systems/combat/BreakingStatusEffects.d.ts +0 -4
  535. package/lib/systems/combat/BreakingStatusEffects.d.ts.map +1 -1
  536. package/lib/systems/combat/BreakingStatusEffects.js +0 -3
  537. package/lib/systems/combat/BreakingStatusEffects.js.map +1 -1
  538. package/lib/systems/combat/CombatStateSystem.d.ts +0 -9
  539. package/lib/systems/combat/CombatStateSystem.d.ts.map +1 -1
  540. package/lib/systems/combat/CombatStateSystem.js +0 -9
  541. package/lib/systems/combat/CombatStateSystem.js.map +1 -1
  542. package/lib/systems/combat/ConsciousnessSystem.d.ts +0 -16
  543. package/lib/systems/combat/ConsciousnessSystem.d.ts.map +1 -1
  544. package/lib/systems/combat/ConsciousnessSystem.js +0 -16
  545. package/lib/systems/combat/ConsciousnessSystem.js.map +1 -1
  546. package/lib/systems/combat/FallIntegration.d.ts +0 -3
  547. package/lib/systems/combat/FallIntegration.d.ts.map +1 -1
  548. package/lib/systems/combat/FallIntegration.js +0 -3
  549. package/lib/systems/combat/FallIntegration.js.map +1 -1
  550. package/lib/systems/combat/GrappleSystem.d.ts +0 -2
  551. package/lib/systems/combat/GrappleSystem.d.ts.map +1 -1
  552. package/lib/systems/combat/GrappleSystem.js +0 -2
  553. package/lib/systems/combat/GrappleSystem.js.map +1 -1
  554. package/lib/systems/combat/LimbExposureSystem.d.ts +0 -7
  555. package/lib/systems/combat/LimbExposureSystem.d.ts.map +1 -1
  556. package/lib/systems/combat/LimbExposureSystem.js +0 -7
  557. package/lib/systems/combat/LimbExposureSystem.js.map +1 -1
  558. package/lib/systems/combat/PainResponseSystem.d.ts +0 -11
  559. package/lib/systems/combat/PainResponseSystem.d.ts.map +1 -1
  560. package/lib/systems/combat/PainResponseSystem.js +0 -11
  561. package/lib/systems/combat/PainResponseSystem.js.map +1 -1
  562. package/lib/systems/combat/painConsciousnessUtils.d.ts +0 -7
  563. package/lib/systems/combat/painConsciousnessUtils.d.ts.map +1 -1
  564. package/lib/systems/combat/painConsciousnessUtils.js +0 -7
  565. package/lib/systems/combat/painConsciousnessUtils.js.map +1 -1
  566. package/lib/systems/effects.d.ts +11 -0
  567. package/lib/systems/effects.d.ts.map +1 -1
  568. package/lib/systems/effects.js +10 -0
  569. package/lib/systems/effects.js.map +1 -1
  570. package/lib/systems/game.d.ts +16 -0
  571. package/lib/systems/game.d.ts.map +1 -1
  572. package/lib/systems/game.js +1 -0
  573. package/lib/systems/game.js.map +1 -1
  574. package/lib/systems/index.d.ts +5 -1
  575. package/lib/systems/index.d.ts.map +1 -1
  576. package/lib/systems/index.js.map +1 -1
  577. package/lib/systems/movement/InjuryMovementModifier.d.ts +0 -10
  578. package/lib/systems/movement/InjuryMovementModifier.d.ts.map +1 -1
  579. package/lib/systems/movement/InjuryMovementModifier.js +0 -7
  580. package/lib/systems/movement/InjuryMovementModifier.js.map +1 -1
  581. package/lib/systems/movement/integration.d.ts +0 -3
  582. package/lib/systems/movement/integration.d.ts.map +1 -1
  583. package/lib/systems/movement/integration.js +0 -3
  584. package/lib/systems/movement/integration.js.map +1 -1
  585. package/lib/systems/physics/AttackMovementPhysics.d.ts +0 -9
  586. package/lib/systems/physics/AttackMovementPhysics.d.ts.map +1 -1
  587. package/lib/systems/physics/AttackMovementPhysics.js +0 -7
  588. package/lib/systems/physics/AttackMovementPhysics.js.map +1 -1
  589. package/lib/systems/physics/CollisionDetection.d.ts +0 -6
  590. package/lib/systems/physics/CollisionDetection.d.ts.map +1 -1
  591. package/lib/systems/physics/CollisionDetection.js +0 -6
  592. package/lib/systems/physics/CollisionDetection.js.map +1 -1
  593. package/lib/systems/physics/CoordinateMapper.d.ts +0 -1
  594. package/lib/systems/physics/CoordinateMapper.d.ts.map +1 -1
  595. package/lib/systems/physics/CoordinateMapper.js +0 -1
  596. package/lib/systems/physics/CoordinateMapper.js.map +1 -1
  597. package/lib/systems/physics/KnockbackPhysics.d.ts +0 -11
  598. package/lib/systems/physics/KnockbackPhysics.d.ts.map +1 -1
  599. package/lib/systems/physics/KnockbackPhysics.js +0 -8
  600. package/lib/systems/physics/KnockbackPhysics.js.map +1 -1
  601. package/lib/systems/physics/MovementPhysics.d.ts +0 -10
  602. package/lib/systems/physics/MovementPhysics.d.ts.map +1 -1
  603. package/lib/systems/physics/MovementPhysics.js +0 -8
  604. package/lib/systems/physics/MovementPhysics.js.map +1 -1
  605. package/lib/systems/physics/PhysicalReachCalculator.d.ts +0 -6
  606. package/lib/systems/physics/PhysicalReachCalculator.d.ts.map +1 -1
  607. package/lib/systems/physics/PhysicalReachCalculator.js +0 -5
  608. package/lib/systems/physics/PhysicalReachCalculator.js.map +1 -1
  609. package/lib/systems/physics/SpeedModifierSystem.d.ts +0 -5
  610. package/lib/systems/physics/SpeedModifierSystem.d.ts.map +1 -1
  611. package/lib/systems/physics/SpeedModifierSystem.js +0 -4
  612. package/lib/systems/physics/SpeedModifierSystem.js.map +1 -1
  613. package/lib/systems/player.d.ts +0 -5
  614. package/lib/systems/player.d.ts.map +1 -1
  615. package/lib/systems/trigram/TrigramCalculator.d.ts +0 -1
  616. package/lib/systems/trigram/TrigramCalculator.d.ts.map +1 -1
  617. package/lib/systems/trigram/TrigramCalculator.js +0 -1
  618. package/lib/systems/trigram/TrigramCalculator.js.map +1 -1
  619. package/lib/systems/trigram/types.d.ts +0 -4
  620. package/lib/systems/trigram/types.d.ts.map +1 -1
  621. package/lib/systems/trigram/types.js +0 -2
  622. package/lib/systems/trigram/types.js.map +1 -1
  623. package/lib/systems/types.d.ts +7 -2
  624. package/lib/systems/types.d.ts.map +1 -1
  625. package/lib/systems/types.js.map +1 -1
  626. package/lib/systems/vitalpoint/DamageCalculator.d.ts +0 -3
  627. package/lib/systems/vitalpoint/DamageCalculator.d.ts.map +1 -1
  628. package/lib/systems/vitalpoint/DamageCalculator.js +0 -3
  629. package/lib/systems/vitalpoint/DamageCalculator.js.map +1 -1
  630. package/lib/systems/vitalpoint/KoreanVitalPoints.d.ts +0 -8
  631. package/lib/systems/vitalpoint/KoreanVitalPoints.d.ts.map +1 -1
  632. package/lib/systems/vitalpoint/KoreanVitalPoints.js +0 -8
  633. package/lib/systems/vitalpoint/KoreanVitalPoints.js.map +1 -1
  634. package/lib/systems/vitalpoint/VitalPointsData.d.ts +0 -3
  635. package/lib/systems/vitalpoint/VitalPointsData.d.ts.map +1 -1
  636. package/lib/systems/vitalpoint/VitalPointsData.js +0 -1
  637. package/lib/systems/vitalpoint/VitalPointsData.js.map +1 -1
  638. package/lib/types/PhysicsTypes.d.ts +21 -78
  639. package/lib/types/PhysicsTypes.d.ts.map +1 -1
  640. package/lib/types/PhysicsTypes.js +17 -63
  641. package/lib/types/PhysicsTypes.js.map +1 -1
  642. package/lib/types/clothing.d.ts +0 -9
  643. package/lib/types/clothing.d.ts.map +1 -1
  644. package/lib/types/constants/animations.d.ts +35 -1
  645. package/lib/types/constants/animations.d.ts.map +1 -1
  646. package/lib/types/constants/animations.js +12 -1
  647. package/lib/types/constants/animations.js.map +1 -1
  648. package/lib/types/constants/colors.d.ts +28 -2
  649. package/lib/types/constants/colors.d.ts.map +1 -1
  650. package/lib/types/constants/colors.js +30 -4
  651. package/lib/types/constants/colors.js.map +1 -1
  652. package/lib/types/constants/index.d.ts +5 -1
  653. package/lib/types/constants/index.d.ts.map +1 -1
  654. package/lib/types/constants/index.js.map +1 -1
  655. package/lib/types/constants/performance.d.ts +0 -2
  656. package/lib/types/constants/performance.d.ts.map +1 -1
  657. package/lib/types/constants/performance.js +0 -2
  658. package/lib/types/constants/performance.js.map +1 -1
  659. package/lib/types/constants/typography.d.ts +40 -2
  660. package/lib/types/constants/typography.d.ts.map +1 -1
  661. package/lib/types/constants/typography.js +40 -2
  662. package/lib/types/constants/typography.js.map +1 -1
  663. package/lib/types/constants/ui.d.ts +89 -1
  664. package/lib/types/constants/ui.d.ts.map +1 -1
  665. package/lib/types/constants/ui.js +33 -1
  666. package/lib/types/constants/ui.js.map +1 -1
  667. package/lib/types/facial.d.ts +0 -15
  668. package/lib/types/facial.d.ts.map +1 -1
  669. package/lib/types/facial.js +0 -8
  670. package/lib/types/facial.js.map +1 -1
  671. package/lib/types/hand-animation.d.ts +34 -147
  672. package/lib/types/hand-animation.d.ts.map +1 -1
  673. package/lib/types/hand-animation.js +0 -2
  674. package/lib/types/hand-animation.js.map +1 -1
  675. package/lib/types/injury.d.ts +0 -2
  676. package/lib/types/injury.d.ts.map +1 -1
  677. package/lib/types/injury.js +0 -1
  678. package/lib/types/injury.js.map +1 -1
  679. package/lib/types/physics.d.ts +0 -21
  680. package/lib/types/physics.d.ts.map +1 -1
  681. package/lib/types/physics.js +0 -6
  682. package/lib/types/physics.js.map +1 -1
  683. package/lib/types/physicsConstants.d.ts +0 -12
  684. package/lib/types/physicsConstants.d.ts.map +1 -1
  685. package/lib/types/physicsConstants.js +0 -12
  686. package/lib/types/physicsConstants.js.map +1 -1
  687. package/lib/types/player-visual.d.ts +45 -189
  688. package/lib/types/player-visual.d.ts.map +1 -1
  689. package/lib/types/technique.d.ts +1 -5
  690. package/lib/types/technique.d.ts.map +1 -1
  691. package/lib/types/techniqueId.d.ts +0 -1
  692. package/lib/types/techniqueId.d.ts.map +1 -1
  693. package/lib/types/techniqueId.js +0 -1
  694. package/lib/types/techniqueId.js.map +1 -1
  695. package/lib/utils/arenaWorldDimensions.d.ts +0 -11
  696. package/lib/utils/arenaWorldDimensions.d.ts.map +1 -1
  697. package/lib/utils/arenaWorldDimensions.js +0 -6
  698. package/lib/utils/arenaWorldDimensions.js.map +1 -1
  699. package/lib/utils/controlMapping.d.ts +3 -4
  700. package/lib/utils/controlMapping.d.ts.map +1 -1
  701. package/lib/utils/controlMapping.js +1 -2
  702. package/lib/utils/controlMapping.js.map +1 -1
  703. package/lib/utils/deviceDetection.d.ts +0 -5
  704. package/lib/utils/deviceDetection.d.ts.map +1 -1
  705. package/lib/utils/deviceDetection.js +0 -5
  706. package/lib/utils/deviceDetection.js.map +1 -1
  707. package/lib/utils/hapticFeedback.d.ts +23 -95
  708. package/lib/utils/hapticFeedback.d.ts.map +1 -1
  709. package/lib/utils/hapticFeedback.js +9 -39
  710. package/lib/utils/hapticFeedback.js.map +1 -1
  711. package/lib/utils/haptics.d.ts +0 -3
  712. package/lib/utils/haptics.d.ts.map +1 -1
  713. package/lib/utils/haptics.js +0 -1
  714. package/lib/utils/haptics.js.map +1 -1
  715. package/lib/utils/math.d.ts +0 -3
  716. package/lib/utils/math.d.ts.map +1 -1
  717. package/lib/utils/math.js +0 -2
  718. package/lib/utils/math.js.map +1 -1
  719. package/lib/utils/mobileLayoutHelpers.d.ts +0 -3
  720. package/lib/utils/mobileLayoutHelpers.d.ts.map +1 -1
  721. package/lib/utils/mobileLayoutHelpers.js +0 -1
  722. package/lib/utils/mobileLayoutHelpers.js.map +1 -1
  723. package/lib/utils/mobileUIUtils.d.ts +5 -100
  724. package/lib/utils/mobileUIUtils.d.ts.map +1 -1
  725. package/lib/utils/mobileUIUtils.js +0 -9
  726. package/lib/utils/mobileUIUtils.js.map +1 -1
  727. package/lib/utils/physicalAttributeValidation.d.ts.map +1 -1
  728. package/lib/utils/player3DHelpers.d.ts.map +1 -1
  729. package/lib/utils/player3DHelpers.js.map +1 -1
  730. package/lib/utils/responsiveLayoutHelpers.d.ts +0 -65
  731. package/lib/utils/responsiveLayoutHelpers.d.ts.map +1 -1
  732. package/lib/utils/responsiveLayoutHelpers.js +0 -65
  733. package/lib/utils/responsiveLayoutHelpers.js.map +1 -1
  734. package/lib/utils/responsiveOrientationConstants.d.ts +0 -7
  735. package/lib/utils/responsiveOrientationConstants.d.ts.map +1 -1
  736. package/lib/utils/responsiveOrientationConstants.js +0 -7
  737. package/lib/utils/responsiveOrientationConstants.js.map +1 -1
  738. package/lib/utils/safeAreaUtils.d.ts +0 -6
  739. package/lib/utils/safeAreaUtils.d.ts.map +1 -1
  740. package/lib/utils/safeAreaUtils.js +0 -2
  741. package/lib/utils/safeAreaUtils.js.map +1 -1
  742. package/lib/utils/sharedPhysicsConfig.d.ts +0 -4
  743. package/lib/utils/sharedPhysicsConfig.d.ts.map +1 -1
  744. package/lib/utils/sharedPhysicsConfig.js +0 -2
  745. package/lib/utils/sharedPhysicsConfig.js.map +1 -1
  746. package/lib/utils/skeletonScaling.d.ts +0 -9
  747. package/lib/utils/skeletonScaling.d.ts.map +1 -1
  748. package/lib/utils/skeletonScaling.js +0 -1
  749. package/lib/utils/skeletonScaling.js.map +1 -1
  750. package/package.json +11 -11
@@ -1 +1 @@
1
- {"version":3,"file":"CombatParticleEffects3D.js","names":[],"sources":["../../../../../../src/components/screens/combat/components/effects/CombatParticleEffects3D.tsx"],"sourcesContent":["/**\n * CombatParticleEffects3D - Particle effects coordinator for combat\n * 전투 입자 효과 통합 관리\n *\n * Maps HitEffect events to advanced particle effects:\n * - BloodViscosity3D for blood physics on hits\n * - InternalDamage3D for organ damage visualization on vital point strikes\n * - ParticleAudio3D for synchronized combat audio\n *\n * @module components/effects\n * @category Combat Effects\n * @korean 전투입자효과\n */\n\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport type { HitEffect } from \"../../../../../systems\";\nimport { HitEffectType } from \"../../../../../systems/effects\";\nimport {\n BloodViscosity3D,\n type BloodViscosityEffect,\n type ViscosityType,\n} from \"./BloodViscosity3D\";\nimport {\n InternalDamage3D,\n type InternalDamageEffect,\n type OrganType,\n type PenetrationDepth,\n} from \"./InternalDamage3D\";\nimport {\n ParticleAudio3D,\n type ParticleAudioTrigger,\n type ParticleEffectType,\n} from \"./ParticleAudio3D\";\n\n/**\n * Props for CombatParticleEffects3D\n */\nexport interface CombatParticleEffects3DProps {\n /** Active hit effects from the combat state */\n readonly hitEffects: readonly HitEffect[];\n /** Whether effects are enabled */\n readonly enabled?: boolean;\n /** Mobile optimization flag */\n readonly isMobile?: boolean;\n}\n\n/**\n * Map HitEffectType → blood viscosity type\n * 타격 유형 → 혈액 점도 매핑\n */\nfunction getViscosityForHitType(type: HitEffectType): ViscosityType | null {\n switch (type) {\n case HitEffectType.HIT:\n return \"thin\";\n case HitEffectType.COUNTER:\n return \"medium\";\n case HitEffectType.CRITICAL_HIT:\n return \"thick\";\n case HitEffectType.VITAL_POINT_STRIKE:\n return \"gout\";\n default:\n return null;\n }\n}\n\n/**\n * Map HitEffectType → organ type based on strike position\n * 급소 유형 → 장기 매핑 (타격 위치 기반)\n */\nfunction getOrganForPosition(\n position: { x: number; y: number } | undefined,\n): OrganType {\n if (!position) return \"stomach\";\n // Map y-position to organ (based on typical character model height)\n const y = position.y;\n if (y > 1.4) return \"heart\"; // 심장 - upper chest\n if (y > 1.1) return \"stomach\"; // 명치 - solar plexus\n if (y > 0.8) return \"liver\"; // 간 - right side mid-torso\n if (y > 0.5) return \"spleen\"; // 비장 - left side mid-torso\n return \"kidney\"; // 신장 - lower back\n}\n\n/**\n * Map HitEffect intensity → penetration depth\n * 타격 강도 → 관통 깊이 매핑\n */\nfunction getPenetrationDepth(intensity: number): PenetrationDepth {\n if (intensity >= 1.5) return \"critical\";\n if (intensity >= 1.0) return \"deep\";\n if (intensity >= 0.5) return \"shallow\";\n return \"surface\";\n}\n\n/**\n * Map HitEffectType → audio effect type\n * 타격 유형 → 오디오 효과 매핑\n */\nfunction getAudioEffectType(type: HitEffectType): ParticleEffectType | null {\n switch (type) {\n case HitEffectType.HIT:\n case HitEffectType.COUNTER:\n return \"viscosity\";\n case HitEffectType.CRITICAL_HIT:\n return \"bone\";\n case HitEffectType.VITAL_POINT_STRIKE:\n return \"organ\";\n case HitEffectType.BLOCK:\n case HitEffectType.PARRY:\n return \"bone\";\n default:\n return null;\n }\n}\n\n/** Maximum concurrent effects to prevent performance issues */\nconst MAX_BLOOD_EFFECTS = 8;\nconst MAX_ORGAN_EFFECTS = 4;\n\n/**\n * Simple deterministic hash from string → [0, 1)\n * Used for deterministic direction calculations inside useMemo\n */\nfunction hashToFloat(str: string): number {\n let hash = 0;\n for (let i = 0; i < str.length; i++) {\n hash = (hash * 31 + str.charCodeAt(i)) | 0;\n }\n return Math.abs(hash % 10000) / 10000;\n}\n\n/**\n * CombatParticleEffects3D - Coordinates particle effects for combat\n *\n * Converts HitEffect events into:\n * - Blood viscosity particles (thin/medium/thick/gout based on strike type)\n * - Internal organ damage pulses (for vital point strikes)\n * - Synchronized audio triggers\n *\n * @korean 전투 입자 효과 통합 (타격→혈액물리+장기손상+오디오)\n */\nexport const CombatParticleEffects3D: React.FC<\n CombatParticleEffects3DProps\n> = ({ hitEffects, enabled = true, isMobile = false }) => {\n // Track processed hit effect IDs to avoid duplicates\n const processedIds = useRef<Set<string>>(new Set());\n\n // Effect state arrays\n const [bloodEffects, setBloodEffects] = useState<BloodViscosityEffect[]>([]);\n const [organEffects, setOrganEffects] = useState<InternalDamageEffect[]>([]);\n const [audioTriggers, setAudioTriggers] = useState<ParticleAudioTrigger[]>(\n [],\n );\n\n // Process new HitEffects in useEffect (not during render)\n useEffect(() => {\n const newBlood: BloodViscosityEffect[] = [];\n const newOrgan: InternalDamageEffect[] = [];\n const newAudio: ParticleAudioTrigger[] = [];\n\n for (const hit of hitEffects) {\n if (processedIds.current.has(hit.id)) continue;\n processedIds.current.add(hit.id);\n\n const pos: [number, number, number] = [\n hit.position?.x ?? 0,\n hit.position?.y ?? 1.0,\n 0,\n ];\n\n // Blood viscosity effect\n const viscosity = getViscosityForHitType(hit.type);\n if (viscosity) {\n // Direction: deterministic spray based on hit ID\n const angle = hashToFloat(hit.id) * Math.PI * 2;\n const ySpread = 0.3 + hashToFloat(hit.id + \"_y\") * 0.4;\n const dir: [number, number, number] = [\n Math.cos(angle) * 0.5,\n ySpread,\n Math.sin(angle) * 0.5,\n ];\n\n newBlood.push({\n id: `blood_${hit.id}`,\n position: pos,\n direction: dir,\n viscosityType: viscosity,\n intensity: Math.min(1, hit.intensity),\n startTime: hit.startTime,\n });\n }\n\n // Internal damage for vital point strikes\n if (hit.type === HitEffectType.VITAL_POINT_STRIKE) {\n newOrgan.push({\n id: `organ_${hit.id}`,\n position: pos,\n organType: getOrganForPosition(hit.position),\n penetrationDepth: getPenetrationDepth(hit.intensity),\n startTime: hit.startTime,\n });\n }\n\n // Audio trigger\n const audioType = getAudioEffectType(hit.type);\n if (audioType) {\n newAudio.push({\n effectType: audioType,\n intensity: Math.min(1, hit.intensity),\n timestamp: hit.timestamp,\n });\n }\n }\n\n // Batch merge with existing effects (respecting limits)\n if (newBlood.length > 0) {\n setBloodEffects((prev) =>\n [...prev, ...newBlood].slice(-MAX_BLOOD_EFFECTS),\n );\n }\n if (newOrgan.length > 0) {\n setOrganEffects((prev) =>\n [...prev, ...newOrgan].slice(-MAX_ORGAN_EFFECTS),\n );\n }\n if (newAudio.length > 0) {\n setAudioTriggers((prev) => [...prev, ...newAudio]);\n }\n\n // Clean up old processed IDs periodically\n if (processedIds.current.size > 500) {\n const arr = Array.from(processedIds.current);\n processedIds.current = new Set(arr.slice(-250));\n }\n }, [hitEffects]);\n\n // Effect completion handlers\n const handleBloodComplete = useCallback((id: string) => {\n setBloodEffects((prev) => prev.filter((e) => e.id !== id));\n }, []);\n\n const handleOrganComplete = useCallback((id: string) => {\n setOrganEffects((prev) => prev.filter((e) => e.id !== id));\n }, []);\n\n const handleAudioProcessed = useCallback((timestamp: number) => {\n setAudioTriggers((prev) => prev.filter((t) => t.timestamp !== timestamp));\n }, []);\n\n if (!enabled) return null;\n\n return (\n <>\n {/* Blood Viscosity Particles - 혈액 점도 입자 */}\n <BloodViscosity3D\n effects={bloodEffects}\n enabled={enabled}\n isMobile={isMobile}\n onEffectComplete={handleBloodComplete}\n />\n\n {/* Internal Organ Damage Pulses - 장기 손상 시각화 */}\n <InternalDamage3D\n effects={organEffects}\n enabled={enabled}\n isMobile={isMobile}\n onEffectComplete={handleOrganComplete}\n />\n\n {/* Audio Coordination - 입자 효과 오디오 동기화 */}\n <ParticleAudio3D\n triggers={audioTriggers}\n enabled={enabled}\n onTriggerProcessed={handleAudioProcessed}\n />\n </>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"CombatParticleEffects3D.js","names":[],"sources":["../../../../../../src/components/screens/combat/components/effects/CombatParticleEffects3D.tsx"],"sourcesContent":["/**\n * CombatParticleEffects3D - Particle effects coordinator for combat\n * 전투 입자 효과 통합 관리\n *\n * Maps HitEffect events to advanced particle effects:\n * - BloodViscosity3D for blood physics on hits\n * - InternalDamage3D for organ damage visualization on vital point strikes\n * - ParticleAudio3D for synchronized combat audio\n *\n * @module components/effects\n * @category Combat Effects\n * @korean 전투입자효과\n */\n\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport type { HitEffect } from \"../../../../../systems\";\nimport { HitEffectType } from \"../../../../../systems/effects\";\nimport {\n BloodViscosity3D,\n type BloodViscosityEffect,\n type ViscosityType,\n} from \"./BloodViscosity3D\";\nimport {\n InternalDamage3D,\n type InternalDamageEffect,\n type OrganType,\n type PenetrationDepth,\n} from \"./InternalDamage3D\";\nimport {\n ParticleAudio3D,\n type ParticleAudioTrigger,\n type ParticleEffectType,\n} from \"./ParticleAudio3D\";\n\n/**\n * Props for CombatParticleEffects3D\n */\nexport interface CombatParticleEffects3DProps {\n /** Active hit effects from the combat state */\n readonly hitEffects: readonly HitEffect[];\n /** Whether effects are enabled */\n readonly enabled?: boolean;\n /** Mobile optimization flag */\n readonly isMobile?: boolean;\n}\n\n/**\n * Map HitEffectType → blood viscosity type\n * 타격 유형 → 혈액 점도 매핑\n */\nfunction getViscosityForHitType(type: HitEffectType): ViscosityType | null {\n switch (type) {\n case HitEffectType.HIT:\n return \"thin\";\n case HitEffectType.COUNTER:\n return \"medium\";\n case HitEffectType.CRITICAL_HIT:\n return \"thick\";\n case HitEffectType.VITAL_POINT_STRIKE:\n return \"gout\";\n default:\n return null;\n }\n}\n\n/**\n * Map HitEffectType → organ type based on strike position\n * 급소 유형 → 장기 매핑 (타격 위치 기반)\n */\nfunction getOrganForPosition(\n position: { x: number; y: number } | undefined,\n): OrganType {\n if (!position) return \"stomach\";\n const y = position.y;\n if (y > 1.4) return \"heart\"; // 심장 - upper chest\n if (y > 1.1) return \"stomach\"; // 명치 - solar plexus\n if (y > 0.8) return \"liver\"; // 간 - right side mid-torso\n if (y > 0.5) return \"spleen\"; // 비장 - left side mid-torso\n return \"kidney\"; // 신장 - lower back\n}\n\n/**\n * Map HitEffect intensity → penetration depth\n * 타격 강도 → 관통 깊이 매핑\n */\nfunction getPenetrationDepth(intensity: number): PenetrationDepth {\n if (intensity >= 1.5) return \"critical\";\n if (intensity >= 1.0) return \"deep\";\n if (intensity >= 0.5) return \"shallow\";\n return \"surface\";\n}\n\n/**\n * Map HitEffectType → audio effect type\n * 타격 유형 → 오디오 효과 매핑\n */\nfunction getAudioEffectType(type: HitEffectType): ParticleEffectType | null {\n switch (type) {\n case HitEffectType.HIT:\n case HitEffectType.COUNTER:\n return \"viscosity\";\n case HitEffectType.CRITICAL_HIT:\n return \"bone\";\n case HitEffectType.VITAL_POINT_STRIKE:\n return \"organ\";\n case HitEffectType.BLOCK:\n case HitEffectType.PARRY:\n return \"bone\";\n default:\n return null;\n }\n}\n\n/** Maximum concurrent effects to prevent performance issues */\nconst MAX_BLOOD_EFFECTS = 8;\nconst MAX_ORGAN_EFFECTS = 4;\n\n/**\n * Simple deterministic hash from string → [0, 1)\n * Used for deterministic direction calculations inside useMemo\n */\nfunction hashToFloat(str: string): number {\n let hash = 0;\n for (let i = 0; i < str.length; i++) {\n hash = (hash * 31 + str.charCodeAt(i)) | 0;\n }\n return Math.abs(hash % 10000) / 10000;\n}\n\n/**\n * CombatParticleEffects3D - Coordinates particle effects for combat\n *\n * Converts HitEffect events into:\n * - Blood viscosity particles (thin/medium/thick/gout based on strike type)\n * - Internal organ damage pulses (for vital point strikes)\n * - Synchronized audio triggers\n *\n * @korean 전투 입자 효과 통합 (타격→혈액물리+장기손상+오디오)\n */\nexport const CombatParticleEffects3D: React.FC<\n CombatParticleEffects3DProps\n> = ({ hitEffects, enabled = true, isMobile = false }) => {\n const processedIds = useRef<Set<string>>(new Set());\n\n const [bloodEffects, setBloodEffects] = useState<BloodViscosityEffect[]>([]);\n const [organEffects, setOrganEffects] = useState<InternalDamageEffect[]>([]);\n const [audioTriggers, setAudioTriggers] = useState<ParticleAudioTrigger[]>(\n [],\n );\n\n useEffect(() => {\n const newBlood: BloodViscosityEffect[] = [];\n const newOrgan: InternalDamageEffect[] = [];\n const newAudio: ParticleAudioTrigger[] = [];\n\n for (const hit of hitEffects) {\n if (processedIds.current.has(hit.id)) continue;\n processedIds.current.add(hit.id);\n\n const pos: [number, number, number] = [\n hit.position?.x ?? 0,\n hit.position?.y ?? 1.0,\n 0,\n ];\n\n const viscosity = getViscosityForHitType(hit.type);\n if (viscosity) {\n const angle = hashToFloat(hit.id) * Math.PI * 2;\n const ySpread = 0.3 + hashToFloat(hit.id + \"_y\") * 0.4;\n const dir: [number, number, number] = [\n Math.cos(angle) * 0.5,\n ySpread,\n Math.sin(angle) * 0.5,\n ];\n\n newBlood.push({\n id: `blood_${hit.id}`,\n position: pos,\n direction: dir,\n viscosityType: viscosity,\n intensity: Math.min(1, hit.intensity),\n startTime: hit.startTime,\n });\n }\n\n if (hit.type === HitEffectType.VITAL_POINT_STRIKE) {\n newOrgan.push({\n id: `organ_${hit.id}`,\n position: pos,\n organType: getOrganForPosition(hit.position),\n penetrationDepth: getPenetrationDepth(hit.intensity),\n startTime: hit.startTime,\n });\n }\n\n const audioType = getAudioEffectType(hit.type);\n if (audioType) {\n newAudio.push({\n effectType: audioType,\n intensity: Math.min(1, hit.intensity),\n timestamp: hit.timestamp,\n });\n }\n }\n\n if (newBlood.length > 0) {\n setBloodEffects((prev) =>\n [...prev, ...newBlood].slice(-MAX_BLOOD_EFFECTS),\n );\n }\n if (newOrgan.length > 0) {\n setOrganEffects((prev) =>\n [...prev, ...newOrgan].slice(-MAX_ORGAN_EFFECTS),\n );\n }\n if (newAudio.length > 0) {\n setAudioTriggers((prev) => [...prev, ...newAudio]);\n }\n\n if (processedIds.current.size > 500) {\n const arr = Array.from(processedIds.current);\n processedIds.current = new Set(arr.slice(-250));\n }\n }, [hitEffects]);\n\n const handleBloodComplete = useCallback((id: string) => {\n setBloodEffects((prev) => prev.filter((e) => e.id !== id));\n }, []);\n\n const handleOrganComplete = useCallback((id: string) => {\n setOrganEffects((prev) => prev.filter((e) => e.id !== id));\n }, []);\n\n const handleAudioProcessed = useCallback((timestamp: number) => {\n setAudioTriggers((prev) => prev.filter((t) => t.timestamp !== timestamp));\n }, []);\n\n if (!enabled) return null;\n\n return (\n <>\n {/* Blood Viscosity Particles - 혈액 점도 입자 */}\n <BloodViscosity3D\n effects={bloodEffects}\n enabled={enabled}\n isMobile={isMobile}\n onEffectComplete={handleBloodComplete}\n />\n\n {/* Internal Organ Damage Pulses - 장기 손상 시각화 */}\n <InternalDamage3D\n effects={organEffects}\n enabled={enabled}\n isMobile={isMobile}\n onEffectComplete={handleOrganComplete}\n />\n\n {/* Audio Coordination - 입자 효과 오디오 동기화 */}\n <ParticleAudio3D\n triggers={audioTriggers}\n enabled={enabled}\n onTriggerProcessed={handleAudioProcessed}\n />\n </>\n );\n};\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"ConsciousnessBlur.d.ts","sourceRoot":"","sources":["../../../../../../src/components/screens/combat/components/effects/ConsciousnessBlur.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAkB,MAAM,OAAO,CAAC;AAEvC,MAAM,WAAW,sBAAsB;IACrC;;;;OAIG;IACH,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAE/B;;;OAGG;IACH,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAE3B;;;;;;;OAOG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;CAClC;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,iBAAiB,EAAE,KAAK,CAAC,EAAE,CAAC,sBAAsB,CAsD9D,CAAC"}
1
+ {"version":3,"file":"ConsciousnessBlur.d.ts","sourceRoot":"","sources":["../../../../../../src/components/screens/combat/components/effects/ConsciousnessBlur.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAkB,MAAM,OAAO,CAAC;AAEvC,MAAM,WAAW,sBAAsB;IACrC;;;;OAIG;IACH,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAE/B;;;OAGG;IACH,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAE3B;;;;;;;OAOG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;CAClC;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,iBAAiB,EAAE,KAAK,CAAC,EAAE,CAAC,sBAAsB,CA8C9D,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"ConsciousnessBlur.js","names":[],"sources":["../../../../../../src/components/screens/combat/components/effects/ConsciousnessBlur.tsx"],"sourcesContent":["/**\n * ConsciousnessBlur Component - Visual effect for consciousness impairment\n *\n * Applies a blur effect to the screen that intensifies as consciousness decreases.\n * Uses CSS backdrop-filter for performance-efficient blur rendering.\n *\n * NOTE: This component is rendered OUTSIDE the Canvas as part of the HTML overlay.\n * It does NOT use Html from drei - it's a standard React component.\n *\n * @module components/combat/ConsciousnessBlur\n * @category Combat UI\n * @korean 의식흐림효과\n */\n\nimport React, { useMemo } from \"react\";\n\nexport interface ConsciousnessBlurProps {\n /**\n * Current consciousness level (0-100)\n * 100 = fully conscious, 0 = unconscious\n * @korean 의식수준\n */\n readonly consciousness: number;\n\n /**\n * Mobile responsive mode (reduced blur strength)\n * @korean 모바일여부\n */\n readonly isMobile: boolean;\n\n /**\n * Multiplier applied to the effect's maximum blur + darkening (0.0-1.0).\n *\n * Use this to soften the fullscreen effect when the 3D arena is already\n * visually compressed (e.g. portrait mobile). Default is `1.0`.\n *\n * @korean 효과강도배수\n */\n readonly intensityScale?: number;\n}\n\n/**\n * ConsciousnessBlur - Screen blur effect based on consciousness level\n *\n * Renders a fullscreen overlay with blur effect that intensifies as\n * consciousness decreases. Only visible when consciousness is 90 or below.\n * Optimized for 60fps with CSS backdrop-filter.\n * \n * Accessibility behavior:\n * - Purely decorative visual effect\n * - Marked with aria-hidden=\"true\" and excluded from the accessibility tree\n * - Does not announce consciousness level to screen readers\n * (use a separate, dedicated announcement channel if needed)\n *\n * @example\n * ```tsx\n * <ConsciousnessBlur consciousness={45} isMobile={false} />\n * // No render if consciousness > 90\n * <ConsciousnessBlur consciousness={95} isMobile={false} />\n * ```\n */\nexport const ConsciousnessBlur: React.FC<ConsciousnessBlurProps> = ({\n consciousness,\n isMobile,\n intensityScale = 1,\n}) => {\n const blurStyle = useMemo(() => {\n // Clamp consciousness to 0-100 range\n const clampedConsciousness = Math.max(0, Math.min(100, consciousness));\n\n // Caller-provided attenuation (e.g. 0.5 on portrait mobile).\n const safeScale = Math.max(0, Math.min(1, intensityScale));\n\n // Calculate blur amount (inverse of consciousness)\n // 100 consciousness = 0px blur, 0 consciousness = 12px blur (8px on mobile)\n const maxBlur = (isMobile ? 8 : 12) * safeScale;\n const blurAmount = Math.round(\n ((100 - clampedConsciousness) / 100) * maxBlur\n );\n\n // Also add slight opacity darkening for dramatic effect\n const opacity =\n Math.pow((100 - clampedConsciousness) / 100, 2) * 0.3 * safeScale;\n\n // Don't apply blur if consciousness is high (> 90)\n if (clampedConsciousness > 90) {\n return null;\n }\n\n return {\n position: \"fixed\" as const,\n inset: 0,\n pointerEvents: \"none\" as const,\n backdropFilter: `blur(${blurAmount}px)`,\n WebkitBackdropFilter: `blur(${blurAmount}px)`, // Safari support\n backgroundColor: `rgba(0, 0, 0, ${opacity})`,\n transition:\n \"backdrop-filter 0.5s ease-out, background-color 0.5s ease-out\",\n zIndex: 60, // Above game content but below HUD\n };\n }, [consciousness, isMobile, intensityScale]);\n\n // Don't render if consciousness is very high\n if (consciousness > 90 || !blurStyle) {\n return null;\n }\n\n // Decorative visual overlay; aria-hidden with no live region or additional ARIA roles needed\n return (\n <div\n data-testid=\"consciousness-blur\"\n style={blurStyle}\n aria-hidden=\"true\"\n />\n );\n};\n\nConsciousnessBlur.displayName = \"ConsciousnessBlur\";\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6DA,IAAa,qBAAuD,EAClE,eACA,UACA,iBAAiB,QACb;CACJ,MAAM,YAAY,cAAc;EAE9B,MAAM,uBAAuB,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,cAAc,CAAC;EAGtE,MAAM,YAAY,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,eAAe,CAAC;EAI1D,MAAM,WAAW,WAAW,IAAI,MAAM;EACtC,MAAM,aAAa,KAAK,OACpB,MAAM,wBAAwB,MAAO,QACxC;EAGD,MAAM,UACJ,KAAK,KAAK,MAAM,wBAAwB,KAAK,EAAE,GAAG,KAAM;EAG1D,IAAI,uBAAuB,IACzB,OAAO;EAGT,OAAO;GACL,UAAU;GACV,OAAO;GACP,eAAe;GACf,gBAAgB,QAAQ,WAAW;GACnC,sBAAsB,QAAQ,WAAW;GACzC,iBAAiB,iBAAiB,QAAQ;GAC1C,YACE;GACF,QAAQ;GACT;IACA;EAAC;EAAe;EAAU;EAAe,CAAC;CAG7C,IAAI,gBAAgB,MAAM,CAAC,WACzB,OAAO;CAIT,OACE,oBAAC,OAAD;EACE,eAAY;EACZ,OAAO;EACP,eAAY;EACZ,CAAA;;AAIN,kBAAkB,cAAc"}
1
+ {"version":3,"file":"ConsciousnessBlur.js","names":[],"sources":["../../../../../../src/components/screens/combat/components/effects/ConsciousnessBlur.tsx"],"sourcesContent":["/**\n * ConsciousnessBlur Component - Visual effect for consciousness impairment\n *\n * Applies a blur effect to the screen that intensifies as consciousness decreases.\n * Uses CSS backdrop-filter for performance-efficient blur rendering.\n *\n * NOTE: This component is rendered OUTSIDE the Canvas as part of the HTML overlay.\n * It does NOT use Html from drei - it's a standard React component.\n *\n * @module components/combat/ConsciousnessBlur\n * @category Combat UI\n * @korean 의식흐림효과\n */\n\nimport React, { useMemo } from \"react\";\n\nexport interface ConsciousnessBlurProps {\n /**\n * Current consciousness level (0-100)\n * 100 = fully conscious, 0 = unconscious\n * @korean 의식수준\n */\n readonly consciousness: number;\n\n /**\n * Mobile responsive mode (reduced blur strength)\n * @korean 모바일여부\n */\n readonly isMobile: boolean;\n\n /**\n * Multiplier applied to the effect's maximum blur + darkening (0.0-1.0).\n *\n * Use this to soften the fullscreen effect when the 3D arena is already\n * visually compressed (e.g. portrait mobile). Default is `1.0`.\n *\n * @korean 효과강도배수\n */\n readonly intensityScale?: number;\n}\n\n/**\n * ConsciousnessBlur - Screen blur effect based on consciousness level\n *\n * Renders a fullscreen overlay with blur effect that intensifies as\n * consciousness decreases. Only visible when consciousness is 90 or below.\n * Optimized for 60fps with CSS backdrop-filter.\n * \n * Accessibility behavior:\n * - Purely decorative visual effect\n * - Marked with aria-hidden=\"true\" and excluded from the accessibility tree\n * - Does not announce consciousness level to screen readers\n * (use a separate, dedicated announcement channel if needed)\n *\n * @example\n * ```tsx\n * <ConsciousnessBlur consciousness={45} isMobile={false} />\n * // No render if consciousness > 90\n * <ConsciousnessBlur consciousness={95} isMobile={false} />\n * ```\n */\nexport const ConsciousnessBlur: React.FC<ConsciousnessBlurProps> = ({\n consciousness,\n isMobile,\n intensityScale = 1,\n}) => {\n const blurStyle = useMemo(() => {\n const clampedConsciousness = Math.max(0, Math.min(100, consciousness));\n\n const safeScale = Math.max(0, Math.min(1, intensityScale));\n\n const maxBlur = (isMobile ? 8 : 12) * safeScale;\n const blurAmount = Math.round(\n ((100 - clampedConsciousness) / 100) * maxBlur\n );\n\n const opacity =\n Math.pow((100 - clampedConsciousness) / 100, 2) * 0.3 * safeScale;\n\n if (clampedConsciousness > 90) {\n return null;\n }\n\n return {\n position: \"fixed\" as const,\n inset: 0,\n pointerEvents: \"none\" as const,\n backdropFilter: `blur(${blurAmount}px)`,\n WebkitBackdropFilter: `blur(${blurAmount}px)`, // Safari support\n backgroundColor: `rgba(0, 0, 0, ${opacity})`,\n transition:\n \"backdrop-filter 0.5s ease-out, background-color 0.5s ease-out\",\n zIndex: 60, // Above game content but below HUD\n };\n }, [consciousness, isMobile, intensityScale]);\n\n if (consciousness > 90 || !blurStyle) {\n return null;\n }\n\n return (\n <div\n data-testid=\"consciousness-blur\"\n style={blurStyle}\n aria-hidden=\"true\"\n />\n );\n};\n\nConsciousnessBlur.displayName = \"ConsciousnessBlur\";\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6DA,IAAa,qBAAuD,EAClE,eACA,UACA,iBAAiB,QACb;CACJ,MAAM,YAAY,cAAc;EAC9B,MAAM,uBAAuB,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,cAAc,CAAC;EAEtE,MAAM,YAAY,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,eAAe,CAAC;EAE1D,MAAM,WAAW,WAAW,IAAI,MAAM;EACtC,MAAM,aAAa,KAAK,OACpB,MAAM,wBAAwB,MAAO,QACxC;EAED,MAAM,UACJ,KAAK,KAAK,MAAM,wBAAwB,KAAK,EAAE,GAAG,KAAM;EAE1D,IAAI,uBAAuB,IACzB,OAAO;EAGT,OAAO;GACL,UAAU;GACV,OAAO;GACP,eAAe;GACf,gBAAgB,QAAQ,WAAW;GACnC,sBAAsB,QAAQ,WAAW;GACzC,iBAAiB,iBAAiB,QAAQ;GAC1C,YACE;GACF,QAAQ;GACT;IACA;EAAC;EAAe;EAAU;EAAe,CAAC;CAE7C,IAAI,gBAAgB,MAAM,CAAC,WACzB,OAAO;CAGT,OACE,oBAAC,OAAD;EACE,eAAY;EACZ,OAAO;EACP,eAAY;EACZ,CAAA;;AAIN,kBAAkB,cAAc"}
@@ -1 +1 @@
1
- {"version":3,"file":"DustClouds3D.d.ts","sourceRoot":"","sources":["../../../../../../src/components/screens/combat/components/effects/DustClouds3D.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAIH,OAAO,KAAqC,MAAM,OAAO,CAAC;AAK1D;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,wBAAwB;IACxB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,wCAAwC;IACxC,QAAQ,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5C,yEAAyE;IACzE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,wCAAwC;IACxC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,yBAAyB;IACzB,QAAQ,CAAC,IAAI,EAAE,UAAU,GAAG,QAAQ,GAAG,OAAO,GAAG,OAAO,GAAG,cAAc,CAAC;CAC3E;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,0CAA0C;IAC1C,QAAQ,CAAC,OAAO,EAAE,SAAS,eAAe,EAAE,CAAC;IAC7C,qCAAqC;IACrC,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B,kDAAkD;IAClD,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,qCAAqC;IACrC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;CACxD;AAsHD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAiKpD,CAAC;AAEF,eAAe,YAAY,CAAC"}
1
+ {"version":3,"file":"DustClouds3D.d.ts","sourceRoot":"","sources":["../../../../../../src/components/screens/combat/components/effects/DustClouds3D.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAIH,OAAO,KAAqC,MAAM,OAAO,CAAC;AAK1D;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,wBAAwB;IACxB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,wCAAwC;IACxC,QAAQ,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5C,yEAAyE;IACzE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,wCAAwC;IACxC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,yBAAyB;IACzB,QAAQ,CAAC,IAAI,EAAE,UAAU,GAAG,QAAQ,GAAG,OAAO,GAAG,OAAO,GAAG,cAAc,CAAC;CAC3E;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,0CAA0C;IAC1C,QAAQ,CAAC,OAAO,EAAE,SAAS,eAAe,EAAE,CAAC;IAC7C,qCAAqC;IACrC,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B,kDAAkD;IAClD,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,qCAAqC;IACrC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;CACxD;AAiHD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAwIpD,CAAC;AAEF,eAAe,YAAY,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"EarthCrackEffect3D.d.ts","sourceRoot":"","sources":["../../../../../../src/components/screens/combat/components/effects/EarthCrackEffect3D.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAGH,OAAO,KAAqC,MAAM,OAAO,CAAC;AAK1D;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,wBAAwB;IACxB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,uDAAuD;IACvD,QAAQ,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5C,6DAA6D;IAC7D,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,wCAAwC;IACxC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,2CAA2C;IAC3C,QAAQ,CAAC,OAAO,EAAE,SAAS,gBAAgB,EAAE,CAAC;IAC9C,4CAA4C;IAC5C,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B,+CAA+C;IAC/C,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,qCAAqC;IACrC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;CACxD;AA4LD,eAAO,MAAM,kBAAkB,EAAE,KAAK,CAAC,EAAE,CAAC,uBAAuB,CAoKhE,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
1
+ {"version":3,"file":"EarthCrackEffect3D.d.ts","sourceRoot":"","sources":["../../../../../../src/components/screens/combat/components/effects/EarthCrackEffect3D.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAGH,OAAO,KAAqC,MAAM,OAAO,CAAC;AAK1D;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,wBAAwB;IACxB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,uDAAuD;IACvD,QAAQ,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5C,6DAA6D;IAC7D,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,wCAAwC;IACxC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,2CAA2C;IAC3C,QAAQ,CAAC,OAAO,EAAE,SAAS,gBAAgB,EAAE,CAAC;IAC9C,4CAA4C;IAC5C,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B,+CAA+C;IAC/C,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,qCAAqC;IACrC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;CACxD;AAqLD,eAAO,MAAM,kBAAkB,EAAE,KAAK,CAAC,EAAE,CAAC,uBAAuB,CAgJhE,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"EarthHealingEffect3D.d.ts","sourceRoot":"","sources":["../../../../../../src/components/screens/combat/components/effects/EarthHealingEffect3D.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAIH,OAAO,KAAqC,MAAM,OAAO,CAAC;AAK1D;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,wBAAwB;IACxB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,6DAA6D;IAC7D,QAAQ,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5C,iCAAiC;IACjC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,wCAAwC;IACxC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACxC,6CAA6C;IAC7C,QAAQ,CAAC,OAAO,EAAE,SAAS,kBAAkB,EAAE,CAAC;IAChD,8CAA8C;IAC9C,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B,kDAAkD;IAClD,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,qCAAqC;IACrC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;CACxD;AAsJD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,eAAO,MAAM,oBAAoB,EAAE,KAAK,CAAC,EAAE,CAAC,yBAAyB,CAuJpE,CAAC;AAEF,eAAe,oBAAoB,CAAC"}
1
+ {"version":3,"file":"EarthHealingEffect3D.d.ts","sourceRoot":"","sources":["../../../../../../src/components/screens/combat/components/effects/EarthHealingEffect3D.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAIH,OAAO,KAAqC,MAAM,OAAO,CAAC;AAK1D;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,wBAAwB;IACxB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,6DAA6D;IAC7D,QAAQ,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5C,iCAAiC;IACjC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,wCAAwC;IACxC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACxC,6CAA6C;IAC7C,QAAQ,CAAC,OAAO,EAAE,SAAS,kBAAkB,EAAE,CAAC;IAChD,8CAA8C;IAC9C,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B,kDAAkD;IAClD,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,qCAAqC;IACrC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;CACxD;AA+ID;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,eAAO,MAAM,oBAAoB,EAAE,KAAK,CAAC,EAAE,CAAC,yBAAyB,CAsIpE,CAAC;AAEF,eAAe,oBAAoB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"ImpactSparks3D.d.ts","sourceRoot":"","sources":["../../../../../../src/components/screens/combat/components/effects/ImpactSparks3D.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAIH,OAAO,KAAqC,MAAM,OAAO,CAAC;AAK1D;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,wBAAwB;IACxB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,wCAAwC;IACxC,QAAQ,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5C,kEAAkE;IAClE,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,wCAAwC;IACxC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,iDAAiD;IACjD,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,qCAAqC;IACrC,QAAQ,CAAC,OAAO,EAAE,SAAS,iBAAiB,EAAE,CAAC;IAC/C,sCAAsC;IACtC,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B,kDAAkD;IAClD,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,qCAAqC;IACrC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;CACxD;AA4GD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,eAAO,MAAM,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CAmMxD,CAAC;AAEF,eAAe,cAAc,CAAC"}
1
+ {"version":3,"file":"ImpactSparks3D.d.ts","sourceRoot":"","sources":["../../../../../../src/components/screens/combat/components/effects/ImpactSparks3D.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAIH,OAAO,KAAqC,MAAM,OAAO,CAAC;AAK1D;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,wBAAwB;IACxB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,wCAAwC;IACxC,QAAQ,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5C,kEAAkE;IAClE,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,wCAAwC;IACxC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,iDAAiD;IACjD,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,qCAAqC;IACrC,QAAQ,CAAC,OAAO,EAAE,SAAS,iBAAiB,EAAE,CAAC;IAC/C,sCAAsC;IACtC,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B,kDAAkD;IAClD,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,qCAAqC;IACrC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;CACxD;AAsGD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,eAAO,MAAM,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CA0KxD,CAAC;AAEF,eAAe,cAAc,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"InternalDamage3D.d.ts","sourceRoot":"","sources":["../../../../../../src/components/screens/combat/components/effects/InternalDamage3D.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,KAAqC,MAAM,OAAO,CAAC;AAK1D;;GAEG;AACH,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,OAAO,CAAC;AAE5E;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,SAAS,GAAG,MAAM,GAAG,UAAU,CAAC;AAE3E;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5C,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;IAC9B,QAAQ,CAAC,gBAAgB,EAAE,gBAAgB,CAAC;IAC5C,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,OAAO,EAAE,SAAS,oBAAoB,EAAE,CAAC;IAClD,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;CAClD;AAuCD;;;;;;;;;GASG;AACH,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC,qBAAqB,CAwU5D,CAAC"}
1
+ {"version":3,"file":"InternalDamage3D.d.ts","sourceRoot":"","sources":["../../../../../../src/components/screens/combat/components/effects/InternalDamage3D.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,KAAqC,MAAM,OAAO,CAAC;AAK1D;;GAEG;AACH,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,OAAO,CAAC;AAE5E;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,SAAS,GAAG,MAAM,GAAG,UAAU,CAAC;AAE3E;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5C,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;IAC9B,QAAQ,CAAC,gBAAgB,EAAE,gBAAgB,CAAC;IAC5C,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,OAAO,EAAE,SAAS,oBAAoB,EAAE,CAAC;IAClD,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;CAClD;AA+BD;;;;;;;;;GASG;AACH,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC,qBAAqB,CAwS5D,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"InternalDamage3D.js","names":[],"sources":["../../../../../../src/components/screens/combat/components/effects/InternalDamage3D.tsx"],"sourcesContent":["/**\n * InternalDamage3D - Deep red organ pulses for Korean martial arts organ strikes\n *\n * Priority #4: Internal Damage Visualization\n * - Deep red organ pulses (liver, kidney, spleen, stomach, heart)\n * - Tissue deformation ripples\n * - Penetration depth visualization\n * - Critical organ damage feedback\n *\n * PERFORMANCE OPTIMIZATION (Object Pooling):\n * - Reduced allocations from ~120+ per effect to 2 pooled objects\n * - Pooling strategy:\n * 1. Temporary Color objects for particle initialization use pool\n * 2. Colors are copied to Float32Array (no ownership needed)\n * 3. All pooled objects released after particle system creation\n * - Estimated reduction:\n * - Pulse particles: 60 Color allocations → 1 pooled object\n * - Ripple particles: 30 Color allocations → 1 pooled object\n * - Total: ~90 Color allocations per effect → 2 pooled objects\n *\n * Korean martial arts context (내장 공격 - Internal organ strikes):\n * - 간격 (Liver strike) - Right side body blow\n * - 신장격 (Kidney strike) - Lower back strike\n * - 비장격 (Spleen strike) - Left side body blow\n * - 명치격 (Solar plexus) - Stomach strike\n * - 심장격 (Heart strike) - Chest strike (critical)\n */\n\nimport React, { useEffect, useMemo, useRef } from 'react';\nimport { useFrame } from '@react-three/fiber';\nimport * as THREE from 'three';\nimport { ThreeObjectPools } from '../../../../../utils/threeObjectPool';\n\n/**\n * Organ types for Korean martial arts internal strikes\n */\nexport type OrganType = 'liver' | 'kidney' | 'spleen' | 'stomach' | 'heart';\n\n/**\n * Penetration depth levels for organ damage\n */\nexport type PenetrationDepth = 'surface' | 'shallow' | 'deep' | 'critical';\n\n/**\n * Individual internal damage effect\n */\nexport interface InternalDamageEffect {\n readonly id: string;\n readonly position: [number, number, number];\n readonly organType: OrganType;\n readonly penetrationDepth: PenetrationDepth;\n readonly startTime: number;\n}\n\n/**\n * Props for InternalDamage3D component\n */\nexport interface InternalDamage3DProps {\n readonly effects: readonly InternalDamageEffect[];\n readonly enabled?: boolean;\n readonly isMobile?: boolean;\n readonly onEffectComplete?: (id: string) => void;\n}\n\n// Physics constants for organ damage pulses\nconst INTERNAL_DAMAGE_CONSTANTS = {\n // Pulse expansion speeds\n PULSE_SPEED: 2.5, // m/s expansion rate\n \n // Lifetimes\n PULSE_LIFETIME: 1.5, // seconds for pulse to complete\n RIPPLE_LIFETIME: 0.8, // seconds for tissue ripple\n \n // Max radii by penetration depth\n MAX_RADIUS: {\n surface: 0.4,\n shallow: 0.7,\n deep: 1.0,\n critical: 1.2,\n },\n \n // Intensity multipliers\n INTENSITY: {\n surface: 0.5,\n shallow: 0.8,\n deep: 1.2,\n critical: 1.5,\n },\n \n // Particle counts (desktop)\n PULSE_PARTICLES: 60,\n RIPPLE_PARTICLES: 30,\n \n // Colors\n ORGAN_COLOR: 0x8b0000, // Dark red for organs\n RIPPLE_COLOR: 0xdc143c, // Crimson for tissue ripples\n \n // Emissive intensity\n EMISSIVE_INTENSITY: 0.8,\n} as const;\n\n/**\n * InternalDamage3D - Visualizes internal organ damage with deep red pulses\n *\n * Features:\n * - Expanding sphere pulses from organ impacts\n * - Tissue deformation ripples\n * - Penetration depth-based sizing\n * - Korean martial arts organ strike feedback\n * - Mobile optimization (50% particles)\n */\nexport const InternalDamage3D: React.FC<InternalDamage3DProps> = ({\n effects,\n enabled = true,\n isMobile = false,\n onEffectComplete,\n}) => {\n // Track active effect instances\n const [effectInstances, setEffectInstances] = React.useState<\n Map<\n string,\n {\n pulseParticles: THREE.Points;\n rippleParticles: THREE.Points;\n startTime: number;\n effect: InternalDamageEffect;\n }\n >\n >(new Map());\n\n // Calculate particle counts based on mobile optimization\n const particleCounts = useMemo(() => {\n const pulseCount = isMobile\n ? Math.floor(INTERNAL_DAMAGE_CONSTANTS.PULSE_PARTICLES * 0.5)\n : INTERNAL_DAMAGE_CONSTANTS.PULSE_PARTICLES;\n const rippleCount = isMobile\n ? Math.floor(INTERNAL_DAMAGE_CONSTANTS.RIPPLE_PARTICLES * 0.5)\n : INTERNAL_DAMAGE_CONSTANTS.RIPPLE_PARTICLES;\n return { pulseCount, rippleCount };\n }, [isMobile]);\n\n // Create particle system for organ pulse\n const createPulseParticles = useMemo(\n () => (effect: InternalDamageEffect) => {\n const { pulseCount } = particleCounts;\n const geometry = new THREE.BufferGeometry();\n const positions = new Float32Array(pulseCount * 3);\n const colors = new Float32Array(pulseCount * 3);\n const sizes = new Float32Array(pulseCount);\n\n // Pooled color for calculations - PERFORMANCE: Eliminates pulseCount Color allocations\n const tempColor = ThreeObjectPools.color.acquire();\n\n try {\n // Set color once from pool\n tempColor.set(INTERNAL_DAMAGE_CONSTANTS.ORGAN_COLOR);\n\n // Create sphere distribution\n for (let i = 0; i < pulseCount; i++) {\n // Fibonacci sphere distribution for phi/theta calculations\n // (values calculated but not stored in positions yet - used later for expansion)\n\n positions[i * 3] = 0;\n positions[i * 3 + 1] = 0;\n positions[i * 3 + 2] = 0;\n\n // Dark red color (reuse pooled color)\n colors[i * 3] = tempColor.r;\n colors[i * 3 + 1] = tempColor.g;\n colors[i * 3 + 2] = tempColor.b;\n\n // Size based on penetration depth\n const baseSize = 0.03;\n const depthMultiplier =\n INTERNAL_DAMAGE_CONSTANTS.INTENSITY[effect.penetrationDepth];\n sizes[i] = baseSize * depthMultiplier;\n }\n } finally {\n // Release pooled color back to pool\n ThreeObjectPools.color.release(tempColor);\n }\n\n geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));\n geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));\n geometry.setAttribute('size', new THREE.BufferAttribute(sizes, 1));\n\n const material = new THREE.PointsMaterial({\n size: 0.05,\n vertexColors: true,\n transparent: true,\n opacity: 1.0,\n blending: THREE.AdditiveBlending,\n depthWrite: false,\n sizeAttenuation: true,\n });\n\n const points = new THREE.Points(geometry, material);\n points.position.set(...effect.position);\n\n // Store phi/theta for sphere expansion\n (geometry as THREE.BufferGeometry & { sphereData: Record<string, number | Float32Array> }).sphereData = { positions: positions.slice() };\n for (let i = 0; i < pulseCount; i++) {\n const phi = Math.acos(1 - 2 * (i + 0.5) / pulseCount);\n const theta = Math.PI * (1 + Math.sqrt(5)) * i;\n (geometry as THREE.BufferGeometry & { sphereData: Record<string, number | Float32Array> }).sphereData[`phi_${i}`] = phi;\n (geometry as THREE.BufferGeometry & { sphereData: Record<string, number | Float32Array> }).sphereData[`theta_${i}`] = theta;\n }\n\n return points;\n },\n [particleCounts]\n );\n\n // Create particle system for tissue ripples\n const createRippleParticles = useMemo(\n () => (effect: InternalDamageEffect) => {\n const { rippleCount } = particleCounts;\n const geometry = new THREE.BufferGeometry();\n const positions = new Float32Array(rippleCount * 3);\n const colors = new Float32Array(rippleCount * 3);\n const sizes = new Float32Array(rippleCount);\n\n // Pooled color for calculations - PERFORMANCE: Eliminates rippleCount Color allocations\n const tempColor = ThreeObjectPools.color.acquire();\n\n try {\n // Set color once from pool\n tempColor.set(INTERNAL_DAMAGE_CONSTANTS.RIPPLE_COLOR);\n\n // Create ring distribution\n for (let i = 0; i < rippleCount; i++) {\n const angle = (i / rippleCount) * Math.PI * 2;\n positions[i * 3] = 0;\n positions[i * 3 + 1] = 0;\n positions[i * 3 + 2] = 0;\n\n // Crimson color for ripples (reuse pooled color)\n colors[i * 3] = tempColor.r;\n colors[i * 3 + 1] = tempColor.g;\n colors[i * 3 + 2] = tempColor.b;\n\n sizes[i] = 0.02;\n\n // Store angle for ring expansion\n (geometry as THREE.BufferGeometry & { [key: string]: number })[`angle_${i}`] = angle;\n }\n } finally {\n // Release pooled color back to pool\n ThreeObjectPools.color.release(tempColor);\n }\n\n geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));\n geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));\n geometry.setAttribute('size', new THREE.BufferAttribute(sizes, 1));\n\n const material = new THREE.PointsMaterial({\n size: 0.03,\n vertexColors: true,\n transparent: true,\n opacity: 1.0,\n blending: THREE.NormalBlending,\n depthWrite: false,\n sizeAttenuation: true,\n });\n\n const points = new THREE.Points(geometry, material);\n points.position.set(...effect.position);\n\n return points;\n },\n [particleCounts]\n );\n\n // Update effect instances when effects prop changes\n useEffect(() => {\n if (!enabled) return;\n\n setEffectInstances((prev) => {\n const updated = new Map(prev);\n\n // Add new effects\n effects.forEach((effect) => {\n if (!updated.has(effect.id)) {\n const pulseParticles = createPulseParticles(effect);\n const rippleParticles = createRippleParticles(effect);\n updated.set(effect.id, {\n pulseParticles,\n rippleParticles,\n startTime: effect.startTime,\n effect,\n });\n }\n });\n\n // Remove completed effects\n const currentIds = new Set(effects.map((e) => e.id));\n Array.from(updated.keys()).forEach((id) => {\n if (!currentIds.has(id)) {\n const instance = updated.get(id);\n if (instance) {\n instance.pulseParticles.geometry.dispose();\n (instance.pulseParticles.material as THREE.Material).dispose();\n instance.rippleParticles.geometry.dispose();\n (instance.rippleParticles.material as THREE.Material).dispose();\n }\n updated.delete(id);\n }\n });\n\n return updated;\n });\n }, [effects, enabled, createPulseParticles, createRippleParticles]);\n\n // 자원 정리 | Resource cleanup - Dispose all particle systems on unmount\n // Using a ref to track instances to avoid stale closure issues\n const effectInstancesRef = useRef<Map<\n string,\n {\n pulseParticles: THREE.Points;\n rippleParticles: THREE.Points;\n startTime: number;\n effect: InternalDamageEffect;\n }\n >>(effectInstances);\n useEffect(() => {\n effectInstancesRef.current = effectInstances;\n }, [effectInstances]);\n\n useEffect(() => {\n return () => {\n effectInstancesRef.current.forEach((instance: {\n pulseParticles: THREE.Points;\n rippleParticles: THREE.Points;\n startTime: number;\n effect: InternalDamageEffect;\n }) => {\n instance.pulseParticles.geometry.dispose();\n (instance.pulseParticles.material as THREE.Material).dispose();\n instance.rippleParticles.geometry.dispose();\n (instance.rippleParticles.material as THREE.Material).dispose();\n });\n };\n }, []); // Empty deps - cleanup on unmount only\n\n // Animation loop\n useFrame(() => {\n if (!enabled || effectInstances.size === 0) return;\n\n const now = Date.now();\n const completedIds: string[] = [];\n\n effectInstances.forEach((instance, id) => {\n const elapsed = (now - instance.startTime) / 1000;\n const { effect } = instance;\n\n // Pulse animation\n const pulseProgress = Math.min(\n elapsed / INTERNAL_DAMAGE_CONSTANTS.PULSE_LIFETIME,\n 1.0\n );\n if (pulseProgress < 1.0) {\n const pulseGeometry = instance.pulseParticles.geometry;\n const pulsePositions = pulseGeometry.attributes.position\n .array as Float32Array;\n const maxRadius =\n INTERNAL_DAMAGE_CONSTANTS.MAX_RADIUS[effect.penetrationDepth];\n\n const { pulseCount } = particleCounts;\n const sphereData = (pulseGeometry as THREE.BufferGeometry & { sphereData: Record<string, number | Float32Array> }).sphereData;\n for (let i = 0; i < pulseCount; i++) {\n const phi = sphereData[`phi_${i}`] as number;\n const theta = sphereData[`theta_${i}`] as number;\n const radius = maxRadius * pulseProgress;\n\n pulsePositions[i * 3] = radius * Math.sin(phi) * Math.cos(theta);\n pulsePositions[i * 3 + 1] = radius * Math.sin(phi) * Math.sin(theta);\n pulsePositions[i * 3 + 2] = radius * Math.cos(phi);\n }\n\n pulseGeometry.attributes.position.needsUpdate = true;\n\n // Fade opacity\n const material = instance.pulseParticles.material as THREE.PointsMaterial;\n material.opacity = 1.0 - pulseProgress * 0.7;\n }\n\n // Ripple animation\n const rippleProgress = Math.min(\n elapsed / INTERNAL_DAMAGE_CONSTANTS.RIPPLE_LIFETIME,\n 1.0\n );\n if (rippleProgress < 1.0) {\n const rippleGeometry = instance.rippleParticles.geometry;\n const ripplePositions = rippleGeometry.attributes.position\n .array as Float32Array;\n\n const { rippleCount } = particleCounts;\n const rippleRadius = 0.6 * rippleProgress;\n for (let i = 0; i < rippleCount; i++) {\n const angle = (rippleGeometry as THREE.BufferGeometry & { [key: string]: number })[`angle_${i}`];\n ripplePositions[i * 3] = rippleRadius * Math.cos(angle);\n ripplePositions[i * 3 + 1] = 0;\n ripplePositions[i * 3 + 2] = rippleRadius * Math.sin(angle);\n }\n\n rippleGeometry.attributes.position.needsUpdate = true;\n\n // Fade opacity\n const material = instance.rippleParticles\n .material as THREE.PointsMaterial;\n material.opacity = 1.0 - rippleProgress;\n }\n\n // Check completion\n if (\n elapsed >= INTERNAL_DAMAGE_CONSTANTS.PULSE_LIFETIME &&\n elapsed >= INTERNAL_DAMAGE_CONSTANTS.RIPPLE_LIFETIME\n ) {\n completedIds.push(id);\n }\n });\n\n // Notify completed effects\n completedIds.forEach((id) => {\n onEffectComplete?.(id);\n });\n });\n\n // Render all active particle systems\n return (\n <>\n {Array.from(effectInstances.values()).map((instance) => (\n <React.Fragment key={instance.effect.id}>\n <primitive object={instance.pulseParticles} />\n <primitive object={instance.rippleParticles} />\n </React.Fragment>\n ))}\n </>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"InternalDamage3D.js","names":[],"sources":["../../../../../../src/components/screens/combat/components/effects/InternalDamage3D.tsx"],"sourcesContent":["/**\n * InternalDamage3D - Deep red organ pulses for Korean martial arts organ strikes\n *\n * Priority #4: Internal Damage Visualization\n * - Deep red organ pulses (liver, kidney, spleen, stomach, heart)\n * - Tissue deformation ripples\n * - Penetration depth visualization\n * - Critical organ damage feedback\n *\n * PERFORMANCE OPTIMIZATION (Object Pooling):\n * - Reduced allocations from ~120+ per effect to 2 pooled objects\n * - Pooling strategy:\n * 1. Temporary Color objects for particle initialization use pool\n * 2. Colors are copied to Float32Array (no ownership needed)\n * 3. All pooled objects released after particle system creation\n * - Estimated reduction:\n * - Pulse particles: 60 Color allocations → 1 pooled object\n * - Ripple particles: 30 Color allocations → 1 pooled object\n * - Total: ~90 Color allocations per effect → 2 pooled objects\n *\n * Korean martial arts context (내장 공격 - Internal organ strikes):\n * - 간격 (Liver strike) - Right side body blow\n * - 신장격 (Kidney strike) - Lower back strike\n * - 비장격 (Spleen strike) - Left side body blow\n * - 명치격 (Solar plexus) - Stomach strike\n * - 심장격 (Heart strike) - Chest strike (critical)\n */\n\nimport React, { useEffect, useMemo, useRef } from 'react';\nimport { useFrame } from '@react-three/fiber';\nimport * as THREE from 'three';\nimport { ThreeObjectPools } from '../../../../../utils/threeObjectPool';\n\n/**\n * Organ types for Korean martial arts internal strikes\n */\nexport type OrganType = 'liver' | 'kidney' | 'spleen' | 'stomach' | 'heart';\n\n/**\n * Penetration depth levels for organ damage\n */\nexport type PenetrationDepth = 'surface' | 'shallow' | 'deep' | 'critical';\n\n/**\n * Individual internal damage effect\n */\nexport interface InternalDamageEffect {\n readonly id: string;\n readonly position: [number, number, number];\n readonly organType: OrganType;\n readonly penetrationDepth: PenetrationDepth;\n readonly startTime: number;\n}\n\n/**\n * Props for InternalDamage3D component\n */\nexport interface InternalDamage3DProps {\n readonly effects: readonly InternalDamageEffect[];\n readonly enabled?: boolean;\n readonly isMobile?: boolean;\n readonly onEffectComplete?: (id: string) => void;\n}\n\nconst INTERNAL_DAMAGE_CONSTANTS = {\n PULSE_SPEED: 2.5, // m/s expansion rate\n \n PULSE_LIFETIME: 1.5, // seconds for pulse to complete\n RIPPLE_LIFETIME: 0.8, // seconds for tissue ripple\n \n MAX_RADIUS: {\n surface: 0.4,\n shallow: 0.7,\n deep: 1.0,\n critical: 1.2,\n },\n \n INTENSITY: {\n surface: 0.5,\n shallow: 0.8,\n deep: 1.2,\n critical: 1.5,\n },\n \n PULSE_PARTICLES: 60,\n RIPPLE_PARTICLES: 30,\n \n ORGAN_COLOR: 0x8b0000, // Dark red for organs\n RIPPLE_COLOR: 0xdc143c, // Crimson for tissue ripples\n \n EMISSIVE_INTENSITY: 0.8,\n} as const;\n\n/**\n * InternalDamage3D - Visualizes internal organ damage with deep red pulses\n *\n * Features:\n * - Expanding sphere pulses from organ impacts\n * - Tissue deformation ripples\n * - Penetration depth-based sizing\n * - Korean martial arts organ strike feedback\n * - Mobile optimization (50% particles)\n */\nexport const InternalDamage3D: React.FC<InternalDamage3DProps> = ({\n effects,\n enabled = true,\n isMobile = false,\n onEffectComplete,\n}) => {\n const [effectInstances, setEffectInstances] = React.useState<\n Map<\n string,\n {\n pulseParticles: THREE.Points;\n rippleParticles: THREE.Points;\n startTime: number;\n effect: InternalDamageEffect;\n }\n >\n >(new Map());\n\n const particleCounts = useMemo(() => {\n const pulseCount = isMobile\n ? Math.floor(INTERNAL_DAMAGE_CONSTANTS.PULSE_PARTICLES * 0.5)\n : INTERNAL_DAMAGE_CONSTANTS.PULSE_PARTICLES;\n const rippleCount = isMobile\n ? Math.floor(INTERNAL_DAMAGE_CONSTANTS.RIPPLE_PARTICLES * 0.5)\n : INTERNAL_DAMAGE_CONSTANTS.RIPPLE_PARTICLES;\n return { pulseCount, rippleCount };\n }, [isMobile]);\n\n const createPulseParticles = useMemo(\n () => (effect: InternalDamageEffect) => {\n const { pulseCount } = particleCounts;\n const geometry = new THREE.BufferGeometry();\n const positions = new Float32Array(pulseCount * 3);\n const colors = new Float32Array(pulseCount * 3);\n const sizes = new Float32Array(pulseCount);\n\n const tempColor = ThreeObjectPools.color.acquire();\n\n try {\n tempColor.set(INTERNAL_DAMAGE_CONSTANTS.ORGAN_COLOR);\n\n for (let i = 0; i < pulseCount; i++) {\n\n positions[i * 3] = 0;\n positions[i * 3 + 1] = 0;\n positions[i * 3 + 2] = 0;\n\n colors[i * 3] = tempColor.r;\n colors[i * 3 + 1] = tempColor.g;\n colors[i * 3 + 2] = tempColor.b;\n\n const baseSize = 0.03;\n const depthMultiplier =\n INTERNAL_DAMAGE_CONSTANTS.INTENSITY[effect.penetrationDepth];\n sizes[i] = baseSize * depthMultiplier;\n }\n } finally {\n ThreeObjectPools.color.release(tempColor);\n }\n\n geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));\n geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));\n geometry.setAttribute('size', new THREE.BufferAttribute(sizes, 1));\n\n const material = new THREE.PointsMaterial({\n size: 0.05,\n vertexColors: true,\n transparent: true,\n opacity: 1.0,\n blending: THREE.AdditiveBlending,\n depthWrite: false,\n sizeAttenuation: true,\n });\n\n const points = new THREE.Points(geometry, material);\n points.position.set(...effect.position);\n\n (geometry as THREE.BufferGeometry & { sphereData: Record<string, number | Float32Array> }).sphereData = { positions: positions.slice() };\n for (let i = 0; i < pulseCount; i++) {\n const phi = Math.acos(1 - 2 * (i + 0.5) / pulseCount);\n const theta = Math.PI * (1 + Math.sqrt(5)) * i;\n (geometry as THREE.BufferGeometry & { sphereData: Record<string, number | Float32Array> }).sphereData[`phi_${i}`] = phi;\n (geometry as THREE.BufferGeometry & { sphereData: Record<string, number | Float32Array> }).sphereData[`theta_${i}`] = theta;\n }\n\n return points;\n },\n [particleCounts]\n );\n\n const createRippleParticles = useMemo(\n () => (effect: InternalDamageEffect) => {\n const { rippleCount } = particleCounts;\n const geometry = new THREE.BufferGeometry();\n const positions = new Float32Array(rippleCount * 3);\n const colors = new Float32Array(rippleCount * 3);\n const sizes = new Float32Array(rippleCount);\n\n const tempColor = ThreeObjectPools.color.acquire();\n\n try {\n tempColor.set(INTERNAL_DAMAGE_CONSTANTS.RIPPLE_COLOR);\n\n for (let i = 0; i < rippleCount; i++) {\n const angle = (i / rippleCount) * Math.PI * 2;\n positions[i * 3] = 0;\n positions[i * 3 + 1] = 0;\n positions[i * 3 + 2] = 0;\n\n colors[i * 3] = tempColor.r;\n colors[i * 3 + 1] = tempColor.g;\n colors[i * 3 + 2] = tempColor.b;\n\n sizes[i] = 0.02;\n\n (geometry as THREE.BufferGeometry & { [key: string]: number })[`angle_${i}`] = angle;\n }\n } finally {\n ThreeObjectPools.color.release(tempColor);\n }\n\n geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));\n geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));\n geometry.setAttribute('size', new THREE.BufferAttribute(sizes, 1));\n\n const material = new THREE.PointsMaterial({\n size: 0.03,\n vertexColors: true,\n transparent: true,\n opacity: 1.0,\n blending: THREE.NormalBlending,\n depthWrite: false,\n sizeAttenuation: true,\n });\n\n const points = new THREE.Points(geometry, material);\n points.position.set(...effect.position);\n\n return points;\n },\n [particleCounts]\n );\n\n useEffect(() => {\n if (!enabled) return;\n\n setEffectInstances((prev) => {\n const updated = new Map(prev);\n\n effects.forEach((effect) => {\n if (!updated.has(effect.id)) {\n const pulseParticles = createPulseParticles(effect);\n const rippleParticles = createRippleParticles(effect);\n updated.set(effect.id, {\n pulseParticles,\n rippleParticles,\n startTime: effect.startTime,\n effect,\n });\n }\n });\n\n const currentIds = new Set(effects.map((e) => e.id));\n Array.from(updated.keys()).forEach((id) => {\n if (!currentIds.has(id)) {\n const instance = updated.get(id);\n if (instance) {\n instance.pulseParticles.geometry.dispose();\n (instance.pulseParticles.material as THREE.Material).dispose();\n instance.rippleParticles.geometry.dispose();\n (instance.rippleParticles.material as THREE.Material).dispose();\n }\n updated.delete(id);\n }\n });\n\n return updated;\n });\n }, [effects, enabled, createPulseParticles, createRippleParticles]);\n\n const effectInstancesRef = useRef<Map<\n string,\n {\n pulseParticles: THREE.Points;\n rippleParticles: THREE.Points;\n startTime: number;\n effect: InternalDamageEffect;\n }\n >>(effectInstances);\n useEffect(() => {\n effectInstancesRef.current = effectInstances;\n }, [effectInstances]);\n\n useEffect(() => {\n return () => {\n effectInstancesRef.current.forEach((instance: {\n pulseParticles: THREE.Points;\n rippleParticles: THREE.Points;\n startTime: number;\n effect: InternalDamageEffect;\n }) => {\n instance.pulseParticles.geometry.dispose();\n (instance.pulseParticles.material as THREE.Material).dispose();\n instance.rippleParticles.geometry.dispose();\n (instance.rippleParticles.material as THREE.Material).dispose();\n });\n };\n }, []); // Empty deps - cleanup on unmount only\n\n useFrame(() => {\n if (!enabled || effectInstances.size === 0) return;\n\n const now = Date.now();\n const completedIds: string[] = [];\n\n effectInstances.forEach((instance, id) => {\n const elapsed = (now - instance.startTime) / 1000;\n const { effect } = instance;\n\n const pulseProgress = Math.min(\n elapsed / INTERNAL_DAMAGE_CONSTANTS.PULSE_LIFETIME,\n 1.0\n );\n if (pulseProgress < 1.0) {\n const pulseGeometry = instance.pulseParticles.geometry;\n const pulsePositions = pulseGeometry.attributes.position\n .array as Float32Array;\n const maxRadius =\n INTERNAL_DAMAGE_CONSTANTS.MAX_RADIUS[effect.penetrationDepth];\n\n const { pulseCount } = particleCounts;\n const sphereData = (pulseGeometry as THREE.BufferGeometry & { sphereData: Record<string, number | Float32Array> }).sphereData;\n for (let i = 0; i < pulseCount; i++) {\n const phi = sphereData[`phi_${i}`] as number;\n const theta = sphereData[`theta_${i}`] as number;\n const radius = maxRadius * pulseProgress;\n\n pulsePositions[i * 3] = radius * Math.sin(phi) * Math.cos(theta);\n pulsePositions[i * 3 + 1] = radius * Math.sin(phi) * Math.sin(theta);\n pulsePositions[i * 3 + 2] = radius * Math.cos(phi);\n }\n\n pulseGeometry.attributes.position.needsUpdate = true;\n\n const material = instance.pulseParticles.material as THREE.PointsMaterial;\n material.opacity = 1.0 - pulseProgress * 0.7;\n }\n\n const rippleProgress = Math.min(\n elapsed / INTERNAL_DAMAGE_CONSTANTS.RIPPLE_LIFETIME,\n 1.0\n );\n if (rippleProgress < 1.0) {\n const rippleGeometry = instance.rippleParticles.geometry;\n const ripplePositions = rippleGeometry.attributes.position\n .array as Float32Array;\n\n const { rippleCount } = particleCounts;\n const rippleRadius = 0.6 * rippleProgress;\n for (let i = 0; i < rippleCount; i++) {\n const angle = (rippleGeometry as THREE.BufferGeometry & { [key: string]: number })[`angle_${i}`];\n ripplePositions[i * 3] = rippleRadius * Math.cos(angle);\n ripplePositions[i * 3 + 1] = 0;\n ripplePositions[i * 3 + 2] = rippleRadius * Math.sin(angle);\n }\n\n rippleGeometry.attributes.position.needsUpdate = true;\n\n const material = instance.rippleParticles\n .material as THREE.PointsMaterial;\n material.opacity = 1.0 - rippleProgress;\n }\n\n if (\n elapsed >= INTERNAL_DAMAGE_CONSTANTS.PULSE_LIFETIME &&\n elapsed >= INTERNAL_DAMAGE_CONSTANTS.RIPPLE_LIFETIME\n ) {\n completedIds.push(id);\n }\n });\n\n completedIds.forEach((id) => {\n onEffectComplete?.(id);\n });\n });\n\n return (\n <>\n {Array.from(effectInstances.values()).map((instance) => (\n <React.Fragment key={instance.effect.id}>\n <primitive object={instance.pulseParticles} />\n <primitive object={instance.rippleParticles} />\n </React.Fragment>\n ))}\n </>\n );\n};\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"LiPrecisionTargetingOverlay.d.ts","sourceRoot":"","sources":["../../../../../../src/components/screens/combat/components/effects/LiPrecisionTargetingOverlay.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAA6B,MAAM,OAAO,CAAC;AAclD;;GAEG;AACH,MAAM,WAAW,gCAAgC;IAC/C,mDAAmD;IACnD,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,8CAA8C;IAC9C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,mDAAmD;IACnD,QAAQ,CAAC,cAAc,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnD,wCAAwC;IACxC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,gDAAgD;IAChD,QAAQ,CAAC,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7C,4CAA4C;IAC5C,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7D,+BAA+B;IAC/B,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;CAC5B;AAwBD;;;;GAIG;AACH,eAAO,MAAM,2BAA2B,EAAE,KAAK,CAAC,EAAE,CAAC,gCAAgC,CA+RhF,CAAC"}
1
+ {"version":3,"file":"LiPrecisionTargetingOverlay.d.ts","sourceRoot":"","sources":["../../../../../../src/components/screens/combat/components/effects/LiPrecisionTargetingOverlay.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAA6B,MAAM,OAAO,CAAC;AAclD;;GAEG;AACH,MAAM,WAAW,gCAAgC;IAC/C,mDAAmD;IACnD,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,8CAA8C;IAC9C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,mDAAmD;IACnD,QAAQ,CAAC,cAAc,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnD,wCAAwC;IACxC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,gDAAgD;IAChD,QAAQ,CAAC,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7C,4CAA4C;IAC5C,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7D,+BAA+B;IAC/B,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;CAC5B;AAwBD;;;;GAIG;AACH,eAAO,MAAM,2BAA2B,EAAE,KAAK,CAAC,EAAE,CAAC,gCAAgC,CAmRhF,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"NerveStrikeParticles3D.d.ts","sourceRoot":"","sources":["../../../../../../src/components/screens/combat/components/effects/NerveStrikeParticles3D.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAA4B,MAAM,OAAO,CAAC;AAKjD;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC,uCAAuC;IACvC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IAEpB,gDAAgD;IAChD,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAErD,8DAA8D;IAC9D,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAE/B,wDAAwD;IACxD,QAAQ,CAAC,kBAAkB,EAAE,OAAO,CAAC;IAErC,4CAA4C;IAC5C,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAEhC,yCAAyC;IACzC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,2BAA2B;IAC1C,2CAA2C;IAC3C,QAAQ,CAAC,OAAO,EAAE,SAAS,iBAAiB,EAAE,CAAC;IAE/C,+CAA+C;IAC/C,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAE3B,gEAAgE;IAChE,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAE5B,sDAAsD;IACtD,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;CAClD;AA8BD;;;;;;;;GAQG;AACH,eAAO,MAAM,sBAAsB,EAAE,KAAK,CAAC,EAAE,CAAC,2BAA2B,CAoExE,CAAC"}
1
+ {"version":3,"file":"NerveStrikeParticles3D.d.ts","sourceRoot":"","sources":["../../../../../../src/components/screens/combat/components/effects/NerveStrikeParticles3D.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAA4B,MAAM,OAAO,CAAC;AAKjD;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC,uCAAuC;IACvC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IAEpB,gDAAgD;IAChD,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAErD,8DAA8D;IAC9D,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAE/B,wDAAwD;IACxD,QAAQ,CAAC,kBAAkB,EAAE,OAAO,CAAC;IAErC,4CAA4C;IAC5C,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAEhC,yCAAyC;IACzC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,2BAA2B;IAC1C,2CAA2C;IAC3C,QAAQ,CAAC,OAAO,EAAE,SAAS,iBAAiB,EAAE,CAAC;IAE/C,+CAA+C;IAC/C,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAE3B,gEAAgE;IAChE,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAE5B,sDAAsD;IACtD,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;CAClD;AAyBD;;;;;;;;GAQG;AACH,eAAO,MAAM,sBAAsB,EAAE,KAAK,CAAC,EAAE,CAAC,2BAA2B,CA6DxE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"PainVignette.d.ts","sourceRoot":"","sources":["../../../../../../src/components/screens/combat/components/effects/PainVignette.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAkB,MAAM,OAAO,CAAC;AAGvC,MAAM,WAAW,iBAAiB;IAChC;;;OAGG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAEtB;;;OAGG;IACH,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAE3B;;;;;;;;OAQG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;CAClC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAmDpD,CAAC"}
1
+ {"version":3,"file":"PainVignette.d.ts","sourceRoot":"","sources":["../../../../../../src/components/screens/combat/components/effects/PainVignette.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAkB,MAAM,OAAO,CAAC;AAGvC,MAAM,WAAW,iBAAiB;IAChC;;;OAGG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAEtB;;;OAGG;IACH,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAE3B;;;;;;;;OAQG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;CAClC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CA2CpD,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"PainVignette.js","names":[],"sources":["../../../../../../src/components/screens/combat/components/effects/PainVignette.tsx"],"sourcesContent":["/**\n * PainVignette Component - Visual overlay for pain intensity\n *\n * Displays a red vignette effect around the screen edges that intensifies\n * as the player's pain level increases. Uses CSS box-shadow for performance.\n *\n * NOTE: This component is rendered OUTSIDE the Canvas as part of the HTML overlay.\n * It does NOT use Html from drei - it's a standard React component.\n *\n * @module components/combat/PainVignette\n * @category Combat UI\n * @korean 통증비네트\n */\n\nimport React, { useMemo } from \"react\";\nimport { KOREAN_COLORS } from \"../../../../../types/constants\";\n\nexport interface PainVignetteProps {\n /**\n * Current pain level (0-100)\n * @korean 통증수준\n */\n readonly pain: number;\n\n /**\n * Mobile responsive mode (subtle effects)\n * @korean 모바일여부\n */\n readonly isMobile: boolean;\n\n /**\n * Multiplier applied to the effect's maximum opacity (0.0-1.0).\n *\n * Use this to soften the fullscreen effect when the 3D arena is already\n * visually compressed (e.g. portrait mobile) so the vignette does not\n * further obscure the view. Default is `1.0` (no attenuation).\n *\n * @korean 효과강도배수\n */\n readonly intensityScale?: number;\n}\n\n/**\n * PainVignette - Red edge vignette overlay for pain visualization\n *\n * Renders a fullscreen overlay with red vignette effect that intensifies\n * as pain increases. Only visible when pain is 5 or higher. Optimized\n * for 60fps with CSS transitions.\n * \n * Accessibility:\n * - Purely visual, decorative-only overlay\n * - Hidden from assistive technologies via aria-hidden=\"true\"\n * - Does not announce pain levels; use a separate mechanism if announcements are required\n *\n * @example\n * ```tsx\n * <PainVignette pain={65} isMobile={false} />\n * // No render if pain < 5\n * <PainVignette pain={2} isMobile={false} />\n * ```\n */\nexport const PainVignette: React.FC<PainVignetteProps> = ({\n pain,\n isMobile,\n intensityScale = 1,\n}) => {\n const vignetteStyle = useMemo(() => {\n // Clamp pain to 0-100 range\n const clampedPain = Math.max(0, Math.min(100, pain));\n\n // Calculate intensity (0-1) with cubic easing for dramatic effect\n const normalizedPain = clampedPain / 100;\n const intensity = Math.pow(normalizedPain, 1.5);\n\n // Mobile uses smaller vignette size for subtlety\n const vignetteSize = isMobile ? \"80px\" : \"150px\";\n\n // Maximum opacity is lower on mobile, and can be further attenuated\n // by the caller via `intensityScale` (e.g. portrait mobile).\n const safeScale = Math.max(0, Math.min(1, intensityScale));\n const maxOpacity = (isMobile ? 0.5 : 0.7) * safeScale;\n const opacity = intensity * maxOpacity;\n\n // Use KOREAN_COLORS.PAIN_INDICATOR constant\n const rgb = KOREAN_COLORS.PAIN_INDICATOR;\n const painColor = `rgba(${(rgb >> 16) & 255}, ${(rgb >> 8) & 255}, ${\n rgb & 255\n }, ${opacity})`;\n\n return {\n position: \"fixed\" as const,\n inset: 0,\n pointerEvents: \"none\" as const,\n boxShadow: `inset 0 0 ${vignetteSize} ${painColor}`,\n transition: \"box-shadow 0.5s ease-out\",\n zIndex: 50, // Below UI controls but above game content\n };\n }, [pain, isMobile, intensityScale]);\n\n // Don't render if pain is very low (< 5%)\n if (pain < 5) {\n return null;\n }\n\n // Purely visual overlay - no ARIA roles or live regions; marked aria-hidden to stay decorative\n return (\n <div \n data-testid=\"pain-vignette\" \n style={vignetteStyle} \n aria-hidden=\"true\"\n />\n );\n};\n\nPainVignette.displayName = \"PainVignette\";\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6DA,IAAa,gBAA6C,EACxD,MACA,UACA,iBAAiB,QACb;CACJ,MAAM,gBAAgB,cAAc;EAKlC,MAAM,iBAHc,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,KAAK,CAG5B,GAAc;EACrC,MAAM,YAAY,KAAK,IAAI,gBAAgB,IAAI;EAG/C,MAAM,eAAe,WAAW,SAAS;EAMzC,MAAM,UAAU,cADI,WAAW,KAAM,MADnB,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,eAAe,CACb;EAI5C,MAAM,MAAM,cAAc;EAK1B,OAAO;GACL,UAAU;GACV,OAAO;GACP,eAAe;GACf,WAAW,aAAa,aAAa,GAAG,QARf,OAAO,KAAM,IAAI,IAAK,OAAO,IAAK,IAAI,IAC/D,MAAM,IACP,IAAI,QAAQ;GAOX,YAAY;GACZ,QAAQ;GACT;IACA;EAAC;EAAM;EAAU;EAAe,CAAC;CAGpC,IAAI,OAAO,GACT,OAAO;CAIT,OACE,oBAAC,OAAD;EACE,eAAY;EACZ,OAAO;EACP,eAAY;EACZ,CAAA;;AAIN,aAAa,cAAc"}
1
+ {"version":3,"file":"PainVignette.js","names":[],"sources":["../../../../../../src/components/screens/combat/components/effects/PainVignette.tsx"],"sourcesContent":["/**\n * PainVignette Component - Visual overlay for pain intensity\n *\n * Displays a red vignette effect around the screen edges that intensifies\n * as the player's pain level increases. Uses CSS box-shadow for performance.\n *\n * NOTE: This component is rendered OUTSIDE the Canvas as part of the HTML overlay.\n * It does NOT use Html from drei - it's a standard React component.\n *\n * @module components/combat/PainVignette\n * @category Combat UI\n * @korean 통증비네트\n */\n\nimport React, { useMemo } from \"react\";\nimport { KOREAN_COLORS } from \"../../../../../types/constants\";\n\nexport interface PainVignetteProps {\n /**\n * Current pain level (0-100)\n * @korean 통증수준\n */\n readonly pain: number;\n\n /**\n * Mobile responsive mode (subtle effects)\n * @korean 모바일여부\n */\n readonly isMobile: boolean;\n\n /**\n * Multiplier applied to the effect's maximum opacity (0.0-1.0).\n *\n * Use this to soften the fullscreen effect when the 3D arena is already\n * visually compressed (e.g. portrait mobile) so the vignette does not\n * further obscure the view. Default is `1.0` (no attenuation).\n *\n * @korean 효과강도배수\n */\n readonly intensityScale?: number;\n}\n\n/**\n * PainVignette - Red edge vignette overlay for pain visualization\n *\n * Renders a fullscreen overlay with red vignette effect that intensifies\n * as pain increases. Only visible when pain is 5 or higher. Optimized\n * for 60fps with CSS transitions.\n * \n * Accessibility:\n * - Purely visual, decorative-only overlay\n * - Hidden from assistive technologies via aria-hidden=\"true\"\n * - Does not announce pain levels; use a separate mechanism if announcements are required\n *\n * @example\n * ```tsx\n * <PainVignette pain={65} isMobile={false} />\n * // No render if pain < 5\n * <PainVignette pain={2} isMobile={false} />\n * ```\n */\nexport const PainVignette: React.FC<PainVignetteProps> = ({\n pain,\n isMobile,\n intensityScale = 1,\n}) => {\n const vignetteStyle = useMemo(() => {\n const clampedPain = Math.max(0, Math.min(100, pain));\n\n const normalizedPain = clampedPain / 100;\n const intensity = Math.pow(normalizedPain, 1.5);\n\n const vignetteSize = isMobile ? \"80px\" : \"150px\";\n\n const safeScale = Math.max(0, Math.min(1, intensityScale));\n const maxOpacity = (isMobile ? 0.5 : 0.7) * safeScale;\n const opacity = intensity * maxOpacity;\n\n const rgb = KOREAN_COLORS.PAIN_INDICATOR;\n const painColor = `rgba(${(rgb >> 16) & 255}, ${(rgb >> 8) & 255}, ${\n rgb & 255\n }, ${opacity})`;\n\n return {\n position: \"fixed\" as const,\n inset: 0,\n pointerEvents: \"none\" as const,\n boxShadow: `inset 0 0 ${vignetteSize} ${painColor}`,\n transition: \"box-shadow 0.5s ease-out\",\n zIndex: 50, // Below UI controls but above game content\n };\n }, [pain, isMobile, intensityScale]);\n\n if (pain < 5) {\n return null;\n }\n\n return (\n <div \n data-testid=\"pain-vignette\" \n style={vignetteStyle} \n aria-hidden=\"true\"\n />\n );\n};\n\nPainVignette.displayName = \"PainVignette\";\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6DA,IAAa,gBAA6C,EACxD,MACA,UACA,iBAAiB,QACb;CACJ,MAAM,gBAAgB,cAAc;EAGlC,MAAM,iBAFc,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,KAAK,CAE5B,GAAc;EACrC,MAAM,YAAY,KAAK,IAAI,gBAAgB,IAAI;EAE/C,MAAM,eAAe,WAAW,SAAS;EAIzC,MAAM,UAAU,cADI,WAAW,KAAM,MADnB,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,eAAe,CACb;EAG5C,MAAM,MAAM,cAAc;EAK1B,OAAO;GACL,UAAU;GACV,OAAO;GACP,eAAe;GACf,WAAW,aAAa,aAAa,GAAG,QARf,OAAO,KAAM,IAAI,IAAK,OAAO,IAAK,IAAI,IAC/D,MAAM,IACP,IAAI,QAAQ;GAOX,YAAY;GACZ,QAAQ;GACT;IACA;EAAC;EAAM;EAAU;EAAe,CAAC;CAEpC,IAAI,OAAO,GACT,OAAO;CAGT,OACE,oBAAC,OAAD;EACE,eAAY;EACZ,OAAO;EACP,eAAY;EACZ,CAAA;;AAIN,aAAa,cAAc"}
@@ -1 +1 @@
1
- {"version":3,"file":"ParticleAudio3D.d.ts","sourceRoot":"","sources":["../../../../../../src/components/screens/combat/components/effects/ParticleAudio3D.tsx"],"names":[],"mappings":"AACA;;;;;;;;;;;;;;;GAeG;AAKH;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAC1B,UAAU,GACV,MAAM,GACN,OAAO,GACP,OAAO,GACP,WAAW,CAAC;AAEhB;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,UAAU,EAAE,kBAAkB,CAAC;IACxC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,QAAQ,EAAE,SAAS,oBAAoB,EAAE,CAAC;IACnD,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;CAC3D;AAgCD;;;;;;;;;GASG;AACH,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CAmE1D,CAAC;AAEF;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,kBAAkB,EAC9B,SAAS,EAAE,MAAM,GAChB,oBAAoB,CAMtB"}
1
+ {"version":3,"file":"ParticleAudio3D.d.ts","sourceRoot":"","sources":["../../../../../../src/components/screens/combat/components/effects/ParticleAudio3D.tsx"],"names":[],"mappings":"AACA;;;;;;;;;;;;;;;GAeG;AAKH;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAC1B,UAAU,GACV,MAAM,GACN,OAAO,GACP,OAAO,GACP,WAAW,CAAC;AAEhB;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,UAAU,EAAE,kBAAkB,CAAC;IACxC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,QAAQ,EAAE,SAAS,oBAAoB,EAAE,CAAC;IACnD,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;CAC3D;AA8BD;;;;;;;;;GASG;AACH,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CAwD1D,CAAC;AAEF;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,kBAAkB,EAC9B,SAAS,EAAE,MAAM,GAChB,oBAAoB,CAMtB"}
@@ -1 +1 @@
1
- {"version":3,"file":"ParticleAudio3D.js","names":[],"sources":["../../../../../../src/components/screens/combat/components/effects/ParticleAudio3D.tsx"],"sourcesContent":["/* eslint-disable react-refresh/only-export-components */\n/**\n * ParticleAudio3D - Audio integration for particle effects\n *\n * Priority #6: Combat Audio Integration\n * - Maps particle effects to appropriate sounds\n * - Uses existing sound assets only\n * - Synchronizes with particle lifecycles\n * - Debounces rapid triggers\n *\n * Sound mappings (existing assets):\n * - Arterial spray → ki_release variants (electric energy release)\n * - Bone fractures → block_break variants (bone crack sounds)\n * - Nerve strikes → energy_pulse variants (electric pulse)\n * - Organ damage → hit_flesh + body_realistic_sound (layered impact)\n * - Blood viscosity → hit_flesh variants (lighter flesh impacts)\n */\n\nimport { useEffect, useRef } from \"react\";\nimport { useAudio } from \"../../../../../audio/AudioProvider\";\n\n/**\n * Particle effect types for audio mapping\n */\nexport type ParticleEffectType =\n | \"arterial\"\n | \"bone\"\n | \"nerve\"\n | \"organ\"\n | \"viscosity\";\n\n/**\n * Audio trigger for particle effect\n */\nexport interface ParticleAudioTrigger {\n readonly effectType: ParticleEffectType;\n readonly intensity: number; // 0.0-1.0, affects volume\n readonly timestamp: number; // Used for deduplication\n}\n\n/**\n * Props for ParticleAudio3D component\n */\nexport interface ParticleAudio3DProps {\n readonly triggers: readonly ParticleAudioTrigger[];\n readonly enabled?: boolean;\n readonly onTriggerProcessed?: (timestamp: number) => void;\n}\n\n// Debounce timing (ms) - prevents audio spam\nconst DEBOUNCE_TIME = 100;\n\n// Sound IDs for each effect type (using existing assets)\nconst SOUND_MAPPINGS: Record<ParticleEffectType, string[]> = {\n arterial: [\n \"ki_release\",\n \"ki_release_1\",\n \"ki_release_2\",\n \"ki_release_3\",\n \"ki_release_4\",\n ],\n bone: [\n \"block_break\",\n \"block_break_1\",\n \"block_break_2\",\n \"block_break_3\",\n \"block_break_4\",\n ],\n nerve: [\n \"energy_pulse\",\n \"energy_pulse_1\",\n \"energy_pulse_2\",\n \"energy_pulse_3\",\n \"energy_pulse_4\",\n ],\n organ: [\"hit_flesh\", \"hit_flesh_1\", \"hit_flesh_2\", \"body_realistic_sound\"],\n viscosity: [\"hit_flesh_3\", \"hit_flesh_4\"],\n};\n\n/**\n * ParticleAudio3D - Lightweight audio coordination for particle effects\n *\n * Features:\n * - Debounced audio triggers (max 1 per 100ms per type)\n * - Intensity-based volume scaling\n * - Random sound variant selection\n * - Uses existing audio assets only\n * - No Three.js rendering (pure coordination logic)\n */\nexport const ParticleAudio3D: React.FC<ParticleAudio3DProps> = ({\n triggers,\n enabled = true,\n onTriggerProcessed,\n}) => {\n const audio = useAudio();\n\n // Track last trigger time per effect type for debouncing\n const lastTriggerTime = useRef<Record<ParticleEffectType, number>>({\n arterial: 0,\n bone: 0,\n nerve: 0,\n organ: 0,\n viscosity: 0,\n });\n\n // Track processed trigger timestamps\n const processedTimestamps = useRef<Set<number>>(new Set());\n\n // Process audio triggers\n useEffect(() => {\n if (!enabled || !audio.isInitialized) return;\n\n const now = Date.now();\n\n triggers.forEach((trigger) => {\n // Skip if already processed\n if (processedTimestamps.current.has(trigger.timestamp)) {\n return;\n }\n\n // Check debounce\n const lastTime = lastTriggerTime.current[trigger.effectType];\n if (now - lastTime < DEBOUNCE_TIME) {\n return;\n }\n\n // Get random sound variant for this effect type\n const soundIds = SOUND_MAPPINGS[trigger.effectType];\n const soundId = soundIds[Math.floor(Math.random() * soundIds.length)];\n\n // Play sound (volume based on intensity: 0.3 to 0.9 range)\n try {\n audio.playSFX(soundId);\n } catch (error) {\n console.warn(`Failed to play particle audio: ${soundId}`, error);\n }\n\n // Update tracking\n lastTriggerTime.current[trigger.effectType] = now;\n processedTimestamps.current.add(trigger.timestamp);\n\n // Notify processed\n onTriggerProcessed?.(trigger.timestamp);\n });\n\n // Clean up old processed timestamps (keep last 1000)\n if (processedTimestamps.current.size > 1000) {\n const timestamps = Array.from(processedTimestamps.current).sort(\n (a, b) => b - a,\n );\n processedTimestamps.current = new Set(timestamps.slice(0, 500));\n }\n }, [triggers, enabled, audio, onTriggerProcessed]);\n\n // No visual rendering - pure audio coordination\n return null;\n};\n\n/**\n * Helper function to create audio triggers from particle effects\n */\nexport function createAudioTrigger(\n effectType: ParticleEffectType,\n intensity: number,\n): ParticleAudioTrigger {\n return {\n effectType,\n intensity: Math.max(0, Math.min(1, intensity)),\n timestamp: Date.now(),\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAkDA,IAAM,gBAAgB;AAGtB,IAAM,iBAAuD;CAC3D,UAAU;EACR;EACA;EACA;EACA;EACA;EACD;CACD,MAAM;EACJ;EACA;EACA;EACA;EACA;EACD;CACD,OAAO;EACL;EACA;EACA;EACA;EACA;EACD;CACD,OAAO;EAAC;EAAa;EAAe;EAAe;EAAuB;CAC1E,WAAW,CAAC,eAAe,cAAc;CAC1C;;;;;;;;;;;AAYD,IAAa,mBAAmD,EAC9D,UACA,UAAU,MACV,yBACI;CACJ,MAAM,QAAQ,UAAU;CAGxB,MAAM,kBAAkB,OAA2C;EACjE,UAAU;EACV,MAAM;EACN,OAAO;EACP,OAAO;EACP,WAAW;EACZ,CAAC;CAGF,MAAM,sBAAsB,uBAAoB,IAAI,KAAK,CAAC;CAG1D,gBAAgB;EACd,IAAI,CAAC,WAAW,CAAC,MAAM,eAAe;EAEtC,MAAM,MAAM,KAAK,KAAK;EAEtB,SAAS,SAAS,YAAY;GAE5B,IAAI,oBAAoB,QAAQ,IAAI,QAAQ,UAAU,EACpD;GAKF,IAAI,MADa,gBAAgB,QAAQ,QAAQ,cAC5B,eACnB;GAIF,MAAM,WAAW,eAAe,QAAQ;GACxC,MAAM,UAAU,SAAS,KAAK,MAAM,KAAK,QAAQ,GAAG,SAAS,OAAO;GAGpE,IAAI;IACF,MAAM,QAAQ,QAAQ;YACf,OAAO;IACd,QAAQ,KAAK,kCAAkC,WAAW,MAAM;;GAIlE,gBAAgB,QAAQ,QAAQ,cAAc;GAC9C,oBAAoB,QAAQ,IAAI,QAAQ,UAAU;GAGlD,qBAAqB,QAAQ,UAAU;IACvC;EAGF,IAAI,oBAAoB,QAAQ,OAAO,KAAM;GAC3C,MAAM,aAAa,MAAM,KAAK,oBAAoB,QAAQ,CAAC,MACxD,GAAG,MAAM,IAAI,EACf;GACD,oBAAoB,UAAU,IAAI,IAAI,WAAW,MAAM,GAAG,IAAI,CAAC;;IAEhE;EAAC;EAAU;EAAS;EAAO;EAAmB,CAAC;CAGlD,OAAO"}
1
+ {"version":3,"file":"ParticleAudio3D.js","names":[],"sources":["../../../../../../src/components/screens/combat/components/effects/ParticleAudio3D.tsx"],"sourcesContent":["/* eslint-disable react-refresh/only-export-components */\n/**\n * ParticleAudio3D - Audio integration for particle effects\n *\n * Priority #6: Combat Audio Integration\n * - Maps particle effects to appropriate sounds\n * - Uses existing sound assets only\n * - Synchronizes with particle lifecycles\n * - Debounces rapid triggers\n *\n * Sound mappings (existing assets):\n * - Arterial spray → ki_release variants (electric energy release)\n * - Bone fractures → block_break variants (bone crack sounds)\n * - Nerve strikes → energy_pulse variants (electric pulse)\n * - Organ damage → hit_flesh + body_realistic_sound (layered impact)\n * - Blood viscosity → hit_flesh variants (lighter flesh impacts)\n */\n\nimport { useEffect, useRef } from \"react\";\nimport { useAudio } from \"../../../../../audio/AudioProvider\";\n\n/**\n * Particle effect types for audio mapping\n */\nexport type ParticleEffectType =\n | \"arterial\"\n | \"bone\"\n | \"nerve\"\n | \"organ\"\n | \"viscosity\";\n\n/**\n * Audio trigger for particle effect\n */\nexport interface ParticleAudioTrigger {\n readonly effectType: ParticleEffectType;\n readonly intensity: number; // 0.0-1.0, affects volume\n readonly timestamp: number; // Used for deduplication\n}\n\n/**\n * Props for ParticleAudio3D component\n */\nexport interface ParticleAudio3DProps {\n readonly triggers: readonly ParticleAudioTrigger[];\n readonly enabled?: boolean;\n readonly onTriggerProcessed?: (timestamp: number) => void;\n}\n\nconst DEBOUNCE_TIME = 100;\n\nconst SOUND_MAPPINGS: Record<ParticleEffectType, string[]> = {\n arterial: [\n \"ki_release\",\n \"ki_release_1\",\n \"ki_release_2\",\n \"ki_release_3\",\n \"ki_release_4\",\n ],\n bone: [\n \"block_break\",\n \"block_break_1\",\n \"block_break_2\",\n \"block_break_3\",\n \"block_break_4\",\n ],\n nerve: [\n \"energy_pulse\",\n \"energy_pulse_1\",\n \"energy_pulse_2\",\n \"energy_pulse_3\",\n \"energy_pulse_4\",\n ],\n organ: [\"hit_flesh\", \"hit_flesh_1\", \"hit_flesh_2\", \"body_realistic_sound\"],\n viscosity: [\"hit_flesh_3\", \"hit_flesh_4\"],\n};\n\n/**\n * ParticleAudio3D - Lightweight audio coordination for particle effects\n *\n * Features:\n * - Debounced audio triggers (max 1 per 100ms per type)\n * - Intensity-based volume scaling\n * - Random sound variant selection\n * - Uses existing audio assets only\n * - No Three.js rendering (pure coordination logic)\n */\nexport const ParticleAudio3D: React.FC<ParticleAudio3DProps> = ({\n triggers,\n enabled = true,\n onTriggerProcessed,\n}) => {\n const audio = useAudio();\n\n const lastTriggerTime = useRef<Record<ParticleEffectType, number>>({\n arterial: 0,\n bone: 0,\n nerve: 0,\n organ: 0,\n viscosity: 0,\n });\n\n const processedTimestamps = useRef<Set<number>>(new Set());\n\n useEffect(() => {\n if (!enabled || !audio.isInitialized) return;\n\n const now = Date.now();\n\n triggers.forEach((trigger) => {\n if (processedTimestamps.current.has(trigger.timestamp)) {\n return;\n }\n\n const lastTime = lastTriggerTime.current[trigger.effectType];\n if (now - lastTime < DEBOUNCE_TIME) {\n return;\n }\n\n const soundIds = SOUND_MAPPINGS[trigger.effectType];\n const soundId = soundIds[Math.floor(Math.random() * soundIds.length)];\n\n try {\n audio.playSFX(soundId);\n } catch (error) {\n console.warn(`Failed to play particle audio: ${soundId}`, error);\n }\n\n lastTriggerTime.current[trigger.effectType] = now;\n processedTimestamps.current.add(trigger.timestamp);\n\n onTriggerProcessed?.(trigger.timestamp);\n });\n\n if (processedTimestamps.current.size > 1000) {\n const timestamps = Array.from(processedTimestamps.current).sort(\n (a, b) => b - a,\n );\n processedTimestamps.current = new Set(timestamps.slice(0, 500));\n }\n }, [triggers, enabled, audio, onTriggerProcessed]);\n\n return null;\n};\n\n/**\n * Helper function to create audio triggers from particle effects\n */\nexport function createAudioTrigger(\n effectType: ParticleEffectType,\n intensity: number,\n): ParticleAudioTrigger {\n return {\n effectType,\n intensity: Math.max(0, Math.min(1, intensity)),\n timestamp: Date.now(),\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAiDA,IAAM,gBAAgB;AAEtB,IAAM,iBAAuD;CAC3D,UAAU;EACR;EACA;EACA;EACA;EACA;EACD;CACD,MAAM;EACJ;EACA;EACA;EACA;EACA;EACD;CACD,OAAO;EACL;EACA;EACA;EACA;EACA;EACD;CACD,OAAO;EAAC;EAAa;EAAe;EAAe;EAAuB;CAC1E,WAAW,CAAC,eAAe,cAAc;CAC1C;;;;;;;;;;;AAYD,IAAa,mBAAmD,EAC9D,UACA,UAAU,MACV,yBACI;CACJ,MAAM,QAAQ,UAAU;CAExB,MAAM,kBAAkB,OAA2C;EACjE,UAAU;EACV,MAAM;EACN,OAAO;EACP,OAAO;EACP,WAAW;EACZ,CAAC;CAEF,MAAM,sBAAsB,uBAAoB,IAAI,KAAK,CAAC;CAE1D,gBAAgB;EACd,IAAI,CAAC,WAAW,CAAC,MAAM,eAAe;EAEtC,MAAM,MAAM,KAAK,KAAK;EAEtB,SAAS,SAAS,YAAY;GAC5B,IAAI,oBAAoB,QAAQ,IAAI,QAAQ,UAAU,EACpD;GAIF,IAAI,MADa,gBAAgB,QAAQ,QAAQ,cAC5B,eACnB;GAGF,MAAM,WAAW,eAAe,QAAQ;GACxC,MAAM,UAAU,SAAS,KAAK,MAAM,KAAK,QAAQ,GAAG,SAAS,OAAO;GAEpE,IAAI;IACF,MAAM,QAAQ,QAAQ;YACf,OAAO;IACd,QAAQ,KAAK,kCAAkC,WAAW,MAAM;;GAGlE,gBAAgB,QAAQ,QAAQ,cAAc;GAC9C,oBAAoB,QAAQ,IAAI,QAAQ,UAAU;GAElD,qBAAqB,QAAQ,UAAU;IACvC;EAEF,IAAI,oBAAoB,QAAQ,OAAO,KAAM;GAC3C,MAAM,aAAa,MAAM,KAAK,oBAAoB,QAAQ,CAAC,MACxD,GAAG,MAAM,IAAI,EACf;GACD,oBAAoB,UAAU,IAAI,IAAI,WAAW,MAAM,GAAG,IAAI,CAAC;;IAEhE;EAAC;EAAU;EAAS;EAAO;EAAmB,CAAC;CAElD,OAAO"}
@@ -1 +1 @@
1
- {"version":3,"file":"TraumaOverlay3D.d.ts","sourceRoot":"","sources":["../../../../../../src/components/screens/combat/components/effects/TraumaOverlay3D.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAGH,OAAO,KAAkB,MAAM,OAAO,CAAC;AAIvC,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,6BAA6B,CAAC;AAEjE;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,uCAAuC;IACvC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,6BAA6B;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,mCAAmC;IACnC,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,wCAAwC;IACxC,QAAQ,CAAC,iBAAiB,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACrD,6DAA6D;IAC7D,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,0CAA0C;IAC1C,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;CAClC;AAGD,OAAO,EAAE,UAAU,EAAE,CAAC;AACtB,YAAY,EAAE,MAAM,EAAE,CAAC;AA+LvB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AACH,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CAgE1D,CAAC;AAEF,eAAe,eAAe,CAAC"}
1
+ {"version":3,"file":"TraumaOverlay3D.d.ts","sourceRoot":"","sources":["../../../../../../src/components/screens/combat/components/effects/TraumaOverlay3D.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAGH,OAAO,KAAkB,MAAM,OAAO,CAAC;AAIvC,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,6BAA6B,CAAC;AAEjE;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,uCAAuC;IACvC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,6BAA6B;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,mCAAmC;IACnC,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,wCAAwC;IACxC,QAAQ,CAAC,iBAAiB,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACrD,6DAA6D;IAC7D,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,0CAA0C;IAC1C,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;CAClC;AAED,OAAO,EAAE,UAAU,EAAE,CAAC;AACtB,YAAY,EAAE,MAAM,EAAE,CAAC;AA0LvB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AACH,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CAyD1D,CAAC;AAEF,eAAe,eAAe,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"TraumaOverlay3D.js","names":[],"sources":["../../../../../../src/components/screens/combat/components/effects/TraumaOverlay3D.tsx"],"sourcesContent":["/**\n * TraumaOverlay3D - Bruising and injury visualization system\n *\n * Renders progressive bruising, cuts, and bone fracture indicators on 3D character models\n * using shader-based texture overlays with color blending. Bruises darken with repeated\n * hits to the same body region and persist across combat rounds.\n *\n * Features:\n * - Progressive bruising (purple/black gradients)\n * - Cut/laceration marks for sharp strikes\n * - Bone fracture indicators at <30% health\n * - Injury persistence across rounds\n * - Korean-themed injury visualization\n *\n * @module components/combat/TraumaOverlay3D\n * @category Combat Effects\n * @korean 외상오버레이3D\n */\n\nimport { Html } from \"@react-three/drei\";\nimport React, { useMemo } from \"react\";\nimport * as THREE from \"three\";\nimport { KOREAN_COLORS, FONT_FAMILY } from \"../../../../../types/constants\";\nimport { hexToRgbaString } from \"../../../../../utils/colorUtils\";\nimport { InjuryType, Injury } from \"../../../../../types/injury\";\n\n/**\n * Props for TraumaOverlay3D component\n */\nexport interface TraumaOverlay3DProps {\n /** Character ID for injury tracking */\n readonly playerId: string;\n /** Current health (0-100) */\n readonly health: number;\n /** Active injuries to visualize */\n readonly injuries: readonly Injury[];\n /** Character position in world space */\n readonly characterPosition: [number, number, number];\n /** Whether character is mobile (simplified visualization) */\n readonly isMobile?: boolean;\n /** Whether to show fracture indicators */\n readonly showFractures?: boolean;\n}\n\n// Re-export for backward compatibility\nexport { InjuryType };\nexport type { Injury };\n\n/**\n * Color constants for injury visualization\n */\nconst INJURY_COLORS = {\n BRUISE_FRESH: 0x8B0000, // Dark red (fresh bruise)\n BRUISE_OLD: 0x4B0082, // Indigo (aging bruise)\n BRUISE_SEVERE: 0x000000, // Black (severe bruising)\n CUT_COLOR: 0xFF0000, // Bright red (cut)\n FRACTURE_INDICATOR: KOREAN_COLORS.ACCENT_GOLD, // Gold (bone fracture)\n} as const;\n\n/**\n * Get bruise color based on severity and hit count\n */\nconst getBruiseColor = (severity: number, hitCount: number): number => {\n if (hitCount >= 3 || severity > 0.8) {\n return INJURY_COLORS.BRUISE_SEVERE; // Black for severe/repeated trauma\n } else if (hitCount >= 2 || severity > 0.5) {\n return INJURY_COLORS.BRUISE_OLD; // Indigo for moderate bruising\n } else {\n return INJURY_COLORS.BRUISE_FRESH; // Dark red for fresh bruise\n }\n};\n\n/**\n * Get injury size based on severity\n */\nconst getInjurySize = (severity: number): number => {\n return 0.1 + severity * 0.3; // 0.1 to 0.4 units\n};\n\n/**\n * InjuryMarker - Individual injury visualization\n */\nconst InjuryMarker: React.FC<{\n injury: Injury;\n characterPosition: [number, number, number];\n isMobile: boolean;\n}> = ({ injury, characterPosition, isMobile }) => {\n // Calculate world position relative to character\n const worldPosition: [number, number, number] = useMemo(() => {\n return [\n characterPosition[0] + injury.position[0],\n characterPosition[1] + injury.position[1],\n characterPosition[2] + injury.position[2],\n ];\n }, [characterPosition, injury.position]);\n\n const size = useMemo(() => getInjurySize(injury.severity), [injury.severity]);\n\n // Render based on injury type\n switch (injury.type) {\n case InjuryType.BRUISE: {\n const color = getBruiseColor(injury.severity, injury.hitCount);\n const opacity = Math.min(0.8, 0.3 + injury.severity * 0.5);\n\n return (\n <mesh position={worldPosition} data-testid={`injury-${injury.id}`}>\n <sphereGeometry args={[size, isMobile ? 8 : 16, isMobile ? 8 : 16]} />\n <meshBasicMaterial\n color={color}\n transparent\n opacity={opacity}\n depthTest={true}\n />\n </mesh>\n );\n }\n\n case InjuryType.CUT:\n case InjuryType.LACERATION: {\n const cutLength = injury.type === InjuryType.LACERATION ? size * 3 : size * 2;\n return (\n <group position={worldPosition} data-testid={`injury-${injury.id}`}>\n {/* Cut mark - thin red line */}\n <mesh>\n <boxGeometry args={[cutLength, 0.02, 0.02]} />\n <meshBasicMaterial\n color={INJURY_COLORS.CUT_COLOR}\n transparent\n opacity={0.9}\n />\n </mesh>\n {/* Blood trail for lacerations */}\n {injury.type === InjuryType.LACERATION && (\n <mesh position={[0, -size * 0.5, 0]}>\n <boxGeometry args={[0.02, size, 0.02]} />\n <meshBasicMaterial\n color={KOREAN_COLORS.BLOODLOSS_INDICATOR}\n transparent\n opacity={0.7}\n />\n </mesh>\n )}\n </group>\n );\n }\n\n case InjuryType.FRACTURE: {\n return (\n <group position={worldPosition} data-testid={`injury-${injury.id}`}>\n {/* Fracture indicator - pulsing gold ring */}\n <mesh rotation={[-Math.PI / 2, 0, 0]}>\n <ringGeometry args={[size * 0.8, size, 16]} />\n <meshBasicMaterial\n color={INJURY_COLORS.FRACTURE_INDICATOR}\n transparent\n opacity={0.6}\n side={THREE.DoubleSide}\n />\n </mesh>\n {/* Cross indicator */}\n <mesh>\n <boxGeometry args={[size * 2, 0.02, 0.02]} />\n <meshBasicMaterial\n color={INJURY_COLORS.FRACTURE_INDICATOR}\n transparent\n opacity={0.8}\n />\n </mesh>\n <mesh rotation={[0, 0, Math.PI / 2]}>\n <boxGeometry args={[size * 2, 0.02, 0.02]} />\n <meshBasicMaterial\n color={INJURY_COLORS.FRACTURE_INDICATOR}\n transparent\n opacity={0.8}\n />\n </mesh>\n </group>\n );\n }\n\n default:\n return null;\n }\n};\n\n/**\n * FractureWarning - Html overlay warning for critical bone damage\n * \n * Rendered as a styled Html overlay with Korean/English text and alert semantics.\n */\nconst FractureWarning: React.FC<{\n health: number;\n isMobile: boolean;\n}> = ({ health, isMobile }) => {\n // Calculate opacity before early return to avoid conditional hook call\n const warningOpacity = useMemo(() => {\n // Pulse more intensely as health drops\n const rawOpacity = 0.5 + (30 - health) / 60; // 0.5 at 30% health, 1.0 at 0% health\n // Clamp to valid CSS opacity range [0, 1] in case health falls outside [0, 30]\n return Math.min(1, Math.max(0, rawOpacity));\n }, [health]);\n\n if (health >= 30) return null;\n\n return (\n <Html center position={[0, 2.5, 0]}>\n <div\n style={{\n padding: isMobile ? \"8px 12px\" : \"10px 16px\",\n backgroundColor: hexToRgbaString(INJURY_COLORS.FRACTURE_INDICATOR, warningOpacity * 0.3),\n border: `2px solid ${hexToRgbaString(INJURY_COLORS.FRACTURE_INDICATOR, 1)}`,\n borderRadius: \"6px\",\n fontSize: isMobile ? \"12px\" : \"14px\",\n color: hexToRgbaString(INJURY_COLORS.FRACTURE_INDICATOR, 1),\n fontWeight: \"bold\",\n textShadow: \"0 0 4px rgba(0,0,0,0.8)\",\n animation: \"fracturePulse 1s ease-in-out infinite\",\n fontFamily: FONT_FAMILY.KOREAN,\n }}\n data-testid=\"fracture-warning\"\n role=\"alert\"\n aria-live=\"assertive\"\n >\n ⚠️ 골절위험 | Bone Fracture Risk\n </div>\n <style>\n {`\n @keyframes fracturePulse {\n 0%, 100% { opacity: 0.7; transform: scale(1); }\n 50% { opacity: 1; transform: scale(1.05); }\n }\n `}\n </style>\n </Html>\n );\n};\n\n/**\n * TraumaOverlay3D Component\n *\n * Visualizes progressive combat trauma including bruising, cuts, and bone damage\n * on 3D character models. Injuries persist across rounds and darken with repeated\n * hits to the same body region.\n *\n * @example\n * ```tsx\n * const [injuries, setInjuries] = useState<Injury[]>([]);\n *\n * // On hit event\n * const handleHit = (region: BodyRegion, position: [number, number, number], type: InjuryType) => {\n * const existingInjury = injuries.find(i => \n * i.region === region && \n * distance(i.position, position) < 0.2\n * );\n *\n * if (existingInjury) {\n * // Progressive bruising - increase hit count\n * setInjuries(prev => prev.map(i => \n * i.id === existingInjury.id \n * ? { ...i, hitCount: i.hitCount + 1, severity: Math.min(1.0, i.severity + 0.2) }\n * : i\n * ));\n * } else {\n * // New injury\n * setInjuries([...injuries, {\n * id: generateId(),\n * region,\n * type,\n * position,\n * severity: 0.5,\n * hitCount: 1,\n * timestamp: Date.now(),\n * }]);\n * }\n * };\n *\n * <TraumaOverlay3D\n * playerId={playerId}\n * health={playerHealth}\n * injuries={injuries}\n * characterPosition={characterPosition}\n * isMobile={isMobile}\n * showFractures={true}\n * />\n * ```\n */\nexport const TraumaOverlay3D: React.FC<TraumaOverlay3DProps> = ({\n playerId,\n health,\n injuries,\n characterPosition,\n isMobile = false,\n showFractures = true,\n}) => {\n // Filter injuries for this player\n const playerInjuries = useMemo(() => {\n // In multi-player scenarios, filter by player when available\n if (playerId === null || playerId === undefined) {\n // Single-player or unspecified player: show all injuries\n return injuries;\n }\n\n // Backward-compatible filtering:\n // - If an injury has a playerId, it must match the current playerId.\n // - If an injury has no playerId, include it (legacy/global injuries).\n return injuries.filter((injury) => {\n if (injury.playerId === null || injury.playerId === undefined) {\n return true;\n }\n return injury.playerId === playerId;\n });\n }, [injuries, playerId]);\n\n // Separate fractures from other injuries\n const { fractures, otherInjuries } = useMemo(() => {\n const frac = playerInjuries.filter((i) => i.type === InjuryType.FRACTURE);\n const other = playerInjuries.filter((i) => i.type !== InjuryType.FRACTURE);\n return { fractures: frac, otherInjuries: other };\n }, [playerInjuries]);\n\n return (\n <group data-testid={`trauma-overlay-${playerId}`}>\n {/* Render non-fracture injuries */}\n {otherInjuries.map((injury) => (\n <InjuryMarker\n key={injury.id}\n injury={injury}\n characterPosition={characterPosition}\n isMobile={isMobile}\n />\n ))}\n\n {/* Render fractures if enabled and health is critical */}\n {showFractures &&\n health < 30 &&\n fractures.map((injury) => (\n <InjuryMarker\n key={injury.id}\n injury={injury}\n characterPosition={characterPosition}\n isMobile={isMobile}\n />\n ))}\n\n {/* Fracture warning overlay */}\n {showFractures && health < 30 && fractures.length > 0 && (\n <FractureWarning health={health} isMobile={isMobile} />\n )}\n </group>\n );\n};\n\nexport default TraumaOverlay3D;\n"],"mappings":"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"}
1
+ {"version":3,"file":"TraumaOverlay3D.js","names":[],"sources":["../../../../../../src/components/screens/combat/components/effects/TraumaOverlay3D.tsx"],"sourcesContent":["/**\n * TraumaOverlay3D - Bruising and injury visualization system\n *\n * Renders progressive bruising, cuts, and bone fracture indicators on 3D character models\n * using shader-based texture overlays with color blending. Bruises darken with repeated\n * hits to the same body region and persist across combat rounds.\n *\n * Features:\n * - Progressive bruising (purple/black gradients)\n * - Cut/laceration marks for sharp strikes\n * - Bone fracture indicators at <30% health\n * - Injury persistence across rounds\n * - Korean-themed injury visualization\n *\n * @module components/combat/TraumaOverlay3D\n * @category Combat Effects\n * @korean 외상오버레이3D\n */\n\nimport { Html } from \"@react-three/drei\";\nimport React, { useMemo } from \"react\";\nimport * as THREE from \"three\";\nimport { KOREAN_COLORS, FONT_FAMILY } from \"../../../../../types/constants\";\nimport { hexToRgbaString } from \"../../../../../utils/colorUtils\";\nimport { InjuryType, Injury } from \"../../../../../types/injury\";\n\n/**\n * Props for TraumaOverlay3D component\n */\nexport interface TraumaOverlay3DProps {\n /** Character ID for injury tracking */\n readonly playerId: string;\n /** Current health (0-100) */\n readonly health: number;\n /** Active injuries to visualize */\n readonly injuries: readonly Injury[];\n /** Character position in world space */\n readonly characterPosition: [number, number, number];\n /** Whether character is mobile (simplified visualization) */\n readonly isMobile?: boolean;\n /** Whether to show fracture indicators */\n readonly showFractures?: boolean;\n}\n\nexport { InjuryType };\nexport type { Injury };\n\n/**\n * Color constants for injury visualization\n */\nconst INJURY_COLORS = {\n BRUISE_FRESH: 0x8B0000, // Dark red (fresh bruise)\n BRUISE_OLD: 0x4B0082, // Indigo (aging bruise)\n BRUISE_SEVERE: 0x000000, // Black (severe bruising)\n CUT_COLOR: 0xFF0000, // Bright red (cut)\n FRACTURE_INDICATOR: KOREAN_COLORS.ACCENT_GOLD, // Gold (bone fracture)\n} as const;\n\n/**\n * Get bruise color based on severity and hit count\n */\nconst getBruiseColor = (severity: number, hitCount: number): number => {\n if (hitCount >= 3 || severity > 0.8) {\n return INJURY_COLORS.BRUISE_SEVERE; // Black for severe/repeated trauma\n } else if (hitCount >= 2 || severity > 0.5) {\n return INJURY_COLORS.BRUISE_OLD; // Indigo for moderate bruising\n } else {\n return INJURY_COLORS.BRUISE_FRESH; // Dark red for fresh bruise\n }\n};\n\n/**\n * Get injury size based on severity\n */\nconst getInjurySize = (severity: number): number => {\n return 0.1 + severity * 0.3; // 0.1 to 0.4 units\n};\n\n/**\n * InjuryMarker - Individual injury visualization\n */\nconst InjuryMarker: React.FC<{\n injury: Injury;\n characterPosition: [number, number, number];\n isMobile: boolean;\n}> = ({ injury, characterPosition, isMobile }) => {\n const worldPosition: [number, number, number] = useMemo(() => {\n return [\n characterPosition[0] + injury.position[0],\n characterPosition[1] + injury.position[1],\n characterPosition[2] + injury.position[2],\n ];\n }, [characterPosition, injury.position]);\n\n const size = useMemo(() => getInjurySize(injury.severity), [injury.severity]);\n\n switch (injury.type) {\n case InjuryType.BRUISE: {\n const color = getBruiseColor(injury.severity, injury.hitCount);\n const opacity = Math.min(0.8, 0.3 + injury.severity * 0.5);\n\n return (\n <mesh position={worldPosition} data-testid={`injury-${injury.id}`}>\n <sphereGeometry args={[size, isMobile ? 8 : 16, isMobile ? 8 : 16]} />\n <meshBasicMaterial\n color={color}\n transparent\n opacity={opacity}\n depthTest={true}\n />\n </mesh>\n );\n }\n\n case InjuryType.CUT:\n case InjuryType.LACERATION: {\n const cutLength = injury.type === InjuryType.LACERATION ? size * 3 : size * 2;\n return (\n <group position={worldPosition} data-testid={`injury-${injury.id}`}>\n {/* Cut mark - thin red line */}\n <mesh>\n <boxGeometry args={[cutLength, 0.02, 0.02]} />\n <meshBasicMaterial\n color={INJURY_COLORS.CUT_COLOR}\n transparent\n opacity={0.9}\n />\n </mesh>\n {/* Blood trail for lacerations */}\n {injury.type === InjuryType.LACERATION && (\n <mesh position={[0, -size * 0.5, 0]}>\n <boxGeometry args={[0.02, size, 0.02]} />\n <meshBasicMaterial\n color={KOREAN_COLORS.BLOODLOSS_INDICATOR}\n transparent\n opacity={0.7}\n />\n </mesh>\n )}\n </group>\n );\n }\n\n case InjuryType.FRACTURE: {\n return (\n <group position={worldPosition} data-testid={`injury-${injury.id}`}>\n {/* Fracture indicator - pulsing gold ring */}\n <mesh rotation={[-Math.PI / 2, 0, 0]}>\n <ringGeometry args={[size * 0.8, size, 16]} />\n <meshBasicMaterial\n color={INJURY_COLORS.FRACTURE_INDICATOR}\n transparent\n opacity={0.6}\n side={THREE.DoubleSide}\n />\n </mesh>\n {/* Cross indicator */}\n <mesh>\n <boxGeometry args={[size * 2, 0.02, 0.02]} />\n <meshBasicMaterial\n color={INJURY_COLORS.FRACTURE_INDICATOR}\n transparent\n opacity={0.8}\n />\n </mesh>\n <mesh rotation={[0, 0, Math.PI / 2]}>\n <boxGeometry args={[size * 2, 0.02, 0.02]} />\n <meshBasicMaterial\n color={INJURY_COLORS.FRACTURE_INDICATOR}\n transparent\n opacity={0.8}\n />\n </mesh>\n </group>\n );\n }\n\n default:\n return null;\n }\n};\n\n/**\n * FractureWarning - Html overlay warning for critical bone damage\n * \n * Rendered as a styled Html overlay with Korean/English text and alert semantics.\n */\nconst FractureWarning: React.FC<{\n health: number;\n isMobile: boolean;\n}> = ({ health, isMobile }) => {\n const warningOpacity = useMemo(() => {\n const rawOpacity = 0.5 + (30 - health) / 60; // 0.5 at 30% health, 1.0 at 0% health\n return Math.min(1, Math.max(0, rawOpacity));\n }, [health]);\n\n if (health >= 30) return null;\n\n return (\n <Html center position={[0, 2.5, 0]}>\n <div\n style={{\n padding: isMobile ? \"8px 12px\" : \"10px 16px\",\n backgroundColor: hexToRgbaString(INJURY_COLORS.FRACTURE_INDICATOR, warningOpacity * 0.3),\n border: `2px solid ${hexToRgbaString(INJURY_COLORS.FRACTURE_INDICATOR, 1)}`,\n borderRadius: \"6px\",\n fontSize: isMobile ? \"12px\" : \"14px\",\n color: hexToRgbaString(INJURY_COLORS.FRACTURE_INDICATOR, 1),\n fontWeight: \"bold\",\n textShadow: \"0 0 4px rgba(0,0,0,0.8)\",\n animation: \"fracturePulse 1s ease-in-out infinite\",\n fontFamily: FONT_FAMILY.KOREAN,\n }}\n data-testid=\"fracture-warning\"\n role=\"alert\"\n aria-live=\"assertive\"\n >\n ⚠️ 골절위험 | Bone Fracture Risk\n </div>\n <style>\n {`\n @keyframes fracturePulse {\n 0%, 100% { opacity: 0.7; transform: scale(1); }\n 50% { opacity: 1; transform: scale(1.05); }\n }\n `}\n </style>\n </Html>\n );\n};\n\n/**\n * TraumaOverlay3D Component\n *\n * Visualizes progressive combat trauma including bruising, cuts, and bone damage\n * on 3D character models. Injuries persist across rounds and darken with repeated\n * hits to the same body region.\n *\n * @example\n * ```tsx\n * const [injuries, setInjuries] = useState<Injury[]>([]);\n *\n * // On hit event\n * const handleHit = (region: BodyRegion, position: [number, number, number], type: InjuryType) => {\n * const existingInjury = injuries.find(i => \n * i.region === region && \n * distance(i.position, position) < 0.2\n * );\n *\n * if (existingInjury) {\n * // Progressive bruising - increase hit count\n * setInjuries(prev => prev.map(i => \n * i.id === existingInjury.id \n * ? { ...i, hitCount: i.hitCount + 1, severity: Math.min(1.0, i.severity + 0.2) }\n * : i\n * ));\n * } else {\n * // New injury\n * setInjuries([...injuries, {\n * id: generateId(),\n * region,\n * type,\n * position,\n * severity: 0.5,\n * hitCount: 1,\n * timestamp: Date.now(),\n * }]);\n * }\n * };\n *\n * <TraumaOverlay3D\n * playerId={playerId}\n * health={playerHealth}\n * injuries={injuries}\n * characterPosition={characterPosition}\n * isMobile={isMobile}\n * showFractures={true}\n * />\n * ```\n */\nexport const TraumaOverlay3D: React.FC<TraumaOverlay3DProps> = ({\n playerId,\n health,\n injuries,\n characterPosition,\n isMobile = false,\n showFractures = true,\n}) => {\n const playerInjuries = useMemo(() => {\n if (playerId === null || playerId === undefined) {\n return injuries;\n }\n\n return injuries.filter((injury) => {\n if (injury.playerId === null || injury.playerId === undefined) {\n return true;\n }\n return injury.playerId === playerId;\n });\n }, [injuries, playerId]);\n\n const { fractures, otherInjuries } = useMemo(() => {\n const frac = playerInjuries.filter((i) => i.type === InjuryType.FRACTURE);\n const other = playerInjuries.filter((i) => i.type !== InjuryType.FRACTURE);\n return { fractures: frac, otherInjuries: other };\n }, [playerInjuries]);\n\n return (\n <group data-testid={`trauma-overlay-${playerId}`}>\n {/* Render non-fracture injuries */}\n {otherInjuries.map((injury) => (\n <InjuryMarker\n key={injury.id}\n injury={injury}\n characterPosition={characterPosition}\n isMobile={isMobile}\n />\n ))}\n\n {/* Render fractures if enabled and health is critical */}\n {showFractures &&\n health < 30 &&\n fractures.map((injury) => (\n <InjuryMarker\n key={injury.id}\n injury={injury}\n characterPosition={characterPosition}\n isMobile={isMobile}\n />\n ))}\n\n {/* Fracture warning overlay */}\n {showFractures && health < 30 && fractures.length > 0 && (\n <FractureWarning health={health} isMobile={isMobile} />\n )}\n </group>\n );\n};\n\nexport default TraumaOverlay3D;\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"WaterRipple3D.d.ts","sourceRoot":"","sources":["../../../../../../src/components/screens/combat/components/effects/WaterRipple3D.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAGH,OAAO,KAA0B,MAAM,OAAO,CAAC;AAI/C;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC,wBAAwB;IACxB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,4DAA4D;IAC5D,QAAQ,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5C,gDAAgD;IAChD,QAAQ,CAAC,QAAQ,EAAE,UAAU,GAAG,SAAS,GAAG,UAAU,CAAC;IACvD,wCAAwC;IACxC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,sEAAsE;IACtE,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,sCAAsC;IACtC,QAAQ,CAAC,OAAO,EAAE,SAAS,iBAAiB,EAAE,CAAC;IAC/C,uCAAuC;IACvC,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B,8CAA8C;IAC9C,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,qCAAqC;IACrC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;CACxD;AAmGD;;;GAGG;AACH,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CAyMtD,CAAC;AAEF;;GAEG;AACH,eAAe,aAAa,CAAC"}
1
+ {"version":3,"file":"WaterRipple3D.d.ts","sourceRoot":"","sources":["../../../../../../src/components/screens/combat/components/effects/WaterRipple3D.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAGH,OAAO,KAA0B,MAAM,OAAO,CAAC;AAI/C;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC,wBAAwB;IACxB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,4DAA4D;IAC5D,QAAQ,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5C,gDAAgD;IAChD,QAAQ,CAAC,QAAQ,EAAE,UAAU,GAAG,SAAS,GAAG,UAAU,CAAC;IACvD,wCAAwC;IACxC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,sEAAsE;IACtE,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,sCAAsC;IACtC,QAAQ,CAAC,OAAO,EAAE,SAAS,iBAAiB,EAAE,CAAC;IAC/C,uCAAuC;IACvC,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B,8CAA8C;IAC9C,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,qCAAqC;IACrC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;CACxD;AAmGD;;;GAGG;AACH,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CA4KtD,CAAC;AAEF;;GAEG;AACH,eAAe,aAAa,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"WaterWave3D.d.ts","sourceRoot":"","sources":["../../../../../../src/components/screens/combat/components/effects/WaterWave3D.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAIH,OAAO,KAAqC,MAAM,OAAO,CAAC;AAK1D;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,wBAAwB;IACxB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,6CAA6C;IAC7C,QAAQ,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5C,wDAAwD;IACxD,QAAQ,CAAC,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7C,4CAA4C;IAC5C,QAAQ,CAAC,QAAQ,EAAE,UAAU,GAAG,SAAS,GAAG,UAAU,CAAC;IACvD,2DAA2D;IAC3D,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,wCAAwC;IACxC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,wCAAwC;IACxC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,oCAAoC;IACpC,QAAQ,CAAC,OAAO,EAAE,SAAS,eAAe,EAAE,CAAC;IAC7C,qCAAqC;IACrC,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B,kDAAkD;IAClD,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,qCAAqC;IACrC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;CACxD;AAuLD;;;GAGG;AACH,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,gBAAgB,CAqNlD,CAAC;AAEF;;GAEG;AACH,eAAe,WAAW,CAAC"}
1
+ {"version":3,"file":"WaterWave3D.d.ts","sourceRoot":"","sources":["../../../../../../src/components/screens/combat/components/effects/WaterWave3D.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAIH,OAAO,KAAqC,MAAM,OAAO,CAAC;AAK1D;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,wBAAwB;IACxB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,6CAA6C;IAC7C,QAAQ,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5C,wDAAwD;IACxD,QAAQ,CAAC,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7C,4CAA4C;IAC5C,QAAQ,CAAC,QAAQ,EAAE,UAAU,GAAG,SAAS,GAAG,UAAU,CAAC;IACvD,2DAA2D;IAC3D,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,wCAAwC;IACxC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,wCAAwC;IACxC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,oCAAoC;IACpC,QAAQ,CAAC,OAAO,EAAE,SAAS,eAAe,EAAE,CAAC;IAC7C,qCAAqC;IACrC,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B,kDAAkD;IAClD,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,qCAAqC;IACrC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;CACxD;AA8KD;;;GAGG;AACH,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,gBAAgB,CA+KlD,CAAC;AAEF;;GAEG;AACH,eAAe,WAAW,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/components/screens/combat/components/effects/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAGH,OAAO,EACL,YAAY,EACZ,kBAAkB,GACnB,MAAM,mCAAmC,CAAC;AAC3C,YAAY,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AAG5E,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,YAAY,EACV,mBAAmB,EACnB,qBAAqB,GACtB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,YAAY,EACV,mBAAmB,EACnB,oBAAoB,EACpB,kBAAkB,GACnB,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,YAAY,EACV,eAAe,EACf,yBAAyB,EACzB,YAAY,EACZ,QAAQ,GACT,MAAM,wBAAwB,CAAC;AAGhC,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClE,YAAY,EACV,iBAAiB,EACjB,2BAA2B,GAC5B,MAAM,0BAA0B,CAAC;AAGlC,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,YAAY,EACV,oBAAoB,EACpB,qBAAqB,EACrB,SAAS,EACT,gBAAgB,GACjB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,YAAY,EACV,oBAAoB,EACpB,qBAAqB,EACrB,aAAa,GACd,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACxE,YAAY,EACV,oBAAoB,EACpB,oBAAoB,EACpB,kBAAkB,GACnB,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AACpE,YAAY,EAAE,4BAA4B,EAAE,MAAM,2BAA2B,CAAC;AAG9E,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,YAAY,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAG/E,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,YAAY,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAGzE,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,YAAY,EACV,gBAAgB,EAChB,uBAAuB,GACxB,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,YAAY,EACV,kBAAkB,EAClB,yBAAyB,GAC1B,MAAM,wBAAwB,CAAC;AAKhC,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,+CAA+C,CAAC;AACxF,YAAY,EAAE,iBAAiB,EAAE,MAAM,+CAA+C,CAAC;AAEvF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0EG"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/components/screens/combat/components/effects/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EACL,YAAY,EACZ,kBAAkB,GACnB,MAAM,mCAAmC,CAAC;AAC3C,YAAY,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AAE5E,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,YAAY,EACV,mBAAmB,EACnB,qBAAqB,GACtB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,YAAY,EACV,mBAAmB,EACnB,oBAAoB,EACpB,kBAAkB,GACnB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,YAAY,EACV,eAAe,EACf,yBAAyB,EACzB,YAAY,EACZ,QAAQ,GACT,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClE,YAAY,EACV,iBAAiB,EACjB,2BAA2B,GAC5B,MAAM,0BAA0B,CAAC;AAElC,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,YAAY,EACV,oBAAoB,EACpB,qBAAqB,EACrB,SAAS,EACT,gBAAgB,GACjB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,YAAY,EACV,oBAAoB,EACpB,qBAAqB,EACrB,aAAa,GACd,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACxE,YAAY,EACV,oBAAoB,EACpB,oBAAoB,EACpB,kBAAkB,GACnB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AACpE,YAAY,EAAE,4BAA4B,EAAE,MAAM,2BAA2B,CAAC;AAE9E,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,YAAY,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAE/E,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,YAAY,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAEzE,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,YAAY,EACV,gBAAgB,EAChB,uBAAuB,GACxB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,YAAY,EACV,kBAAkB,EAClB,yBAAyB,GAC1B,MAAM,wBAAwB,CAAC;AAGhC,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,+CAA+C,CAAC;AACxF,YAAY,EAAE,iBAAiB,EAAE,MAAM,+CAA+C,CAAC;AAEvF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0EG"}
@@ -1 +1 @@
1
- {"version":3,"file":"MatchCountdown.d.ts","sourceRoot":"","sources":["../../../../../../src/components/screens/combat/components/feedback/MatchCountdown.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAqC,MAAM,OAAO,CAAC;AAS1D;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,wCAAwC;IACxC,QAAQ,CAAC,UAAU,EAAE,MAAM,IAAI,CAAC;IAChC,qDAAqD;IACrD,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,wCAAwC;IACxC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IAC7B,0CAA0C;IAC1C,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;CAC7B;AA+CD,eAAO,MAAM,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CA+OxD,CAAC;AAEF,eAAe,cAAc,CAAC"}
1
+ {"version":3,"file":"MatchCountdown.d.ts","sourceRoot":"","sources":["../../../../../../src/components/screens/combat/components/feedback/MatchCountdown.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAqC,MAAM,OAAO,CAAC;AAS1D;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,wCAAwC;IACxC,QAAQ,CAAC,UAAU,EAAE,MAAM,IAAI,CAAC;IAChC,qDAAqD;IACrD,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,wCAAwC;IACxC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IAC7B,0CAA0C;IAC1C,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;CAC7B;AA8CD,eAAO,MAAM,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CAoOxD,CAAC;AAEF,eAAe,cAAc,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"MatchCountdown.js","names":[],"sources":["../../../../../../src/components/screens/combat/components/feedback/MatchCountdown.tsx"],"sourcesContent":["/**\n * MatchCountdown Component - Displays match start countdown sequence\n *\n * Korean: 매치 시작 카운트다운 (Match Start Countdown)\n *\n * Shows \"Ready?\" → \"3... 2... 1...\" → \"Fight!\" sequence with animations.\n * Implements Korean cyberpunk aesthetic with bilingual text support.\n * Plays audio cues for countdown and fight announcement.\n *\n * Refactored to use useKoreanTheme for consistent styling.\n *\n * @module components/combat/MatchCountdown\n * @category Combat UI\n */\n\nimport React, { useEffect, useMemo, useRef } from \"react\";\nimport { useAudio } from \"../../../../../audio/AudioProvider\";\nimport {\n MatchCountdownState,\n useMatchCountdown,\n} from \"../../../../../hooks/useMatchCountdown\";\nimport { useKoreanTheme } from \"../../../../shared/base/useKoreanTheme\";\nimport { hexColorToCSS } from \"../../../../../utils/colorUtils\";\n\n/**\n * Props for the MatchCountdown component\n */\nexport interface MatchCountdownProps {\n /** Callback when countdown completes */\n readonly onComplete: () => void;\n /** Whether layout should adapt for mobile screens */\n readonly isMobile: boolean;\n /** Optional callback for skip button */\n readonly onSkip?: () => void;\n /** Whether skip button should be shown */\n readonly showSkip?: boolean;\n}\n\n/**\n * Get display text for current countdown state\n */\nfunction getDisplayText(\n state: MatchCountdownState,\n currentNumber: number\n): {\n ko: string;\n en: string;\n} | null {\n switch (state) {\n case \"ready\":\n return { ko: \"준비?\", en: \"Ready?\" };\n case \"counting\":\n return { ko: String(currentNumber), en: String(currentNumber) };\n case \"fight\":\n return { ko: \"전투!\", en: \"Fight!\" };\n default:\n return null;\n }\n}\n\n/**\n * MatchCountdown Component\n *\n * Displays match start countdown with:\n * - \"Ready?\" announcement (1 second)\n * - Countdown from 3 to 1 (1 second intervals)\n * - \"Fight!\" announcement (1 second)\n * - Pulse/scale animations for emphasis\n * - Bilingual Korean-English text\n * - Audio cues for countdown and fight\n * - Optional skip button\n * - Responsive sizing for mobile/tablet/desktop\n *\n * Korean: 매치 시작 카운트다운 컴포넌트\n */\n// Static config outside component to prevent re-creation on each render\nconst COUNTDOWN_CONFIG = {\n readyDuration: 1,\n countdownInterval: 1,\n fightDuration: 1,\n startNumber: 3,\n} as const;\n\nexport const MatchCountdown: React.FC<MatchCountdownProps> = ({\n onComplete,\n isMobile,\n onSkip,\n showSkip = false,\n}) => {\n const audio = useAudio();\n const theme = useKoreanTheme({ variant: \"primary\", size: \"xlarge\", isMobile });\n\n // Use match countdown hook with stable config reference\n const { state, currentNumber, startCountdown, skipCountdown, isActive } =\n useMatchCountdown(COUNTDOWN_CONFIG, onComplete);\n\n // Track if we've started to avoid double-start in Strict Mode\n const hasStartedRef = useRef(false);\n\n // Auto-start countdown on mount (only once)\n useEffect(() => {\n if (!hasStartedRef.current) {\n hasStartedRef.current = true;\n startCountdown();\n }\n }, [startCountdown]);\n\n // Play audio cues based on state transitions\n useEffect(() => {\n if (!audio.isAudioReady) return;\n\n if (state === \"counting\" && currentNumber > 0) {\n // Play beep for each countdown number\n audio.playSFX(\"attack_light\"); // Using placeholder - will be countdown_beep\n } else if (state === \"fight\") {\n // Play fight announcement\n audio.playSFX(\"attack_heavy\"); // Using placeholder - will be fight_start\n }\n }, [state, currentNumber, audio]);\n\n // Handle skip\n const handleSkip = () => {\n skipCountdown();\n onSkip?.();\n };\n\n // Get display text\n const displayText = getDisplayText(state, currentNumber);\n\n // Calculate responsive font sizes - extracted to avoid nested ternaries\n const getMainFontSize = (): string => {\n if (isMobile) {\n return state === \"fight\" ? \"72px\" : \"64px\";\n }\n return state === \"fight\" ? \"120px\" : \"96px\";\n };\n\n const getSubFontSize = (): string => {\n if (isMobile) {\n return state === \"fight\" ? \"48px\" : \"40px\";\n }\n return state === \"fight\" ? \"72px\" : \"56px\";\n };\n\n const mainFontSize = getMainFontSize();\n const subFontSize = getSubFontSize();\n\n // Memoize colors for performance using theme\n const goldColor = useMemo(() => hexColorToCSS(theme.colors.ACCENT_GOLD), [theme.colors.ACCENT_GOLD]);\n const cyanColor = useMemo(\n () => hexColorToCSS(theme.colors.PRIMARY_CYAN),\n [theme.colors.PRIMARY_CYAN]\n );\n const darkBg = useMemo(\n () => hexColorToCSS(theme.colors.UI_BACKGROUND_DARK),\n [theme.colors.UI_BACKGROUND_DARK]\n );\n\n // Don't render if countdown not active or complete\n if (!isActive || !displayText) {\n return null;\n }\n\n return (\n <>\n <div\n data-testid=\"match-countdown\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label=\"Match countdown in progress\"\n aria-live=\"assertive\"\n style={{\n position: \"fixed\",\n top: 0,\n left: 0,\n width: \"100%\",\n height: \"100%\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n backgroundColor: state === \"fight\" ? `${darkBg}cc` : `${darkBg}ee`,\n zIndex: 1000,\n animation: state === \"ready\" ? \"fadeIn 0.3s ease-in\" : \"none\",\n }}\n >\n <div\n style={{\n fontSize: mainFontSize,\n fontWeight: \"bold\",\n color: state === \"fight\" ? goldColor : cyanColor,\n fontFamily: theme.fontFamily.KOREAN,\n textShadow: `0 0 ${state === \"fight\" ? \"40px\" : \"30px\"} ${\n state === \"fight\" ? goldColor : cyanColor\n }`,\n animation:\n state === \"ready\"\n ? \"pulse 0.8s ease-out\"\n : state === \"counting\"\n ? \"countdownPulse 0.8s ease-out\"\n : state === \"fight\"\n ? \"flash 0.3s ease-out\"\n : \"none\",\n textAlign: \"center\",\n userSelect: \"none\",\n }}\n data-testid=\"countdown-text\"\n >\n {displayText.ko}\n <br />\n <span\n style={{\n fontSize: subFontSize,\n }}\n >\n {displayText.en}\n </span>\n </div>\n\n {/* Optional Skip Button */}\n {showSkip && state !== \"fight\" && (\n <button\n onClick={handleSkip}\n data-testid=\"skip-countdown-button\"\n aria-label=\"Skip countdown\"\n style={{\n position: \"absolute\",\n bottom: isMobile ? \"40px\" : \"60px\",\n padding: isMobile ? \"10px 24px\" : \"12px 32px\",\n fontSize: isMobile ? \"14px\" : \"16px\",\n backgroundColor: cyanColor,\n color: darkBg,\n border: \"none\",\n borderRadius: \"6px\",\n fontFamily: theme.fontFamily.KOREAN,\n fontWeight: \"bold\",\n cursor: \"pointer\",\n transition: \"all 0.2s ease\",\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.transform = \"scale(1.05)\";\n e.currentTarget.style.boxShadow = `0 0 20px ${cyanColor}`;\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.transform = \"scale(1)\";\n e.currentTarget.style.boxShadow = \"none\";\n }}\n onFocus={(e) => {\n e.currentTarget.style.transform = \"scale(1.05)\";\n e.currentTarget.style.boxShadow = `0 0 20px ${cyanColor}`;\n e.currentTarget.style.outline = `2px solid ${cyanColor}`;\n }}\n onBlur={(e) => {\n e.currentTarget.style.transform = \"scale(1)\";\n e.currentTarget.style.boxShadow = \"none\";\n e.currentTarget.style.outline = \"none\";\n }}\n >\n 건너뛰기 | Skip\n </button>\n )}\n </div>\n\n {/* CSS Animations */}\n <style>\n {`\n @keyframes fadeIn {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n }\n\n @keyframes pulse {\n 0% {\n opacity: 0;\n transform: scale(0.9);\n }\n 50% {\n opacity: 1;\n transform: scale(1.05);\n }\n 100% {\n opacity: 1;\n transform: scale(1);\n }\n }\n\n @keyframes countdownPulse {\n 0% {\n opacity: 0;\n transform: scale(1.2);\n }\n 50% {\n opacity: 1;\n transform: scale(1.1);\n }\n 100% {\n opacity: 1;\n transform: scale(1);\n }\n }\n\n @keyframes flash {\n 0% {\n opacity: 0;\n transform: scale(1.5);\n }\n 30% {\n opacity: 1;\n transform: scale(1.3);\n }\n 100% {\n opacity: 1;\n transform: scale(1);\n }\n }\n `}\n </style>\n </>\n );\n};\n\nexport default MatchCountdown;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAyCA,SAAS,eACP,OACA,eAIO;CACP,QAAQ,OAAR;EACE,KAAK,SACH,OAAO;GAAE,IAAI;GAAO,IAAI;GAAU;EACpC,KAAK,YACH,OAAO;GAAE,IAAI,OAAO,cAAc;GAAE,IAAI,OAAO,cAAc;GAAE;EACjE,KAAK,SACH,OAAO;GAAE,IAAI;GAAO,IAAI;GAAU;EACpC,SACE,OAAO;;;;;;;;;;;;;;;;;;AAoBb,IAAM,mBAAmB;CACvB,eAAe;CACf,mBAAmB;CACnB,eAAe;CACf,aAAa;CACd;AAED,IAAa,kBAAiD,EAC5D,YACA,UACA,QACA,WAAW,YACP;CACJ,MAAM,QAAQ,UAAU;CACxB,MAAM,QAAQ,eAAe;EAAE,SAAS;EAAW,MAAM;EAAU;EAAU,CAAC;CAG9E,MAAM,EAAE,OAAO,eAAe,gBAAgB,eAAe,aAC3D,kBAAkB,kBAAkB,WAAW;CAGjD,MAAM,gBAAgB,OAAO,MAAM;CAGnC,gBAAgB;EACd,IAAI,CAAC,cAAc,SAAS;GAC1B,cAAc,UAAU;GACxB,gBAAgB;;IAEjB,CAAC,eAAe,CAAC;CAGpB,gBAAgB;EACd,IAAI,CAAC,MAAM,cAAc;EAEzB,IAAI,UAAU,cAAc,gBAAgB,GAE1C,MAAM,QAAQ,eAAe;OACxB,IAAI,UAAU,SAEnB,MAAM,QAAQ,eAAe;IAE9B;EAAC;EAAO;EAAe;EAAM,CAAC;CAGjC,MAAM,mBAAmB;EACvB,eAAe;EACf,UAAU;;CAIZ,MAAM,cAAc,eAAe,OAAO,cAAc;CAGxD,MAAM,wBAAgC;EACpC,IAAI,UACF,OAAO,UAAU,UAAU,SAAS;EAEtC,OAAO,UAAU,UAAU,UAAU;;CAGvC,MAAM,uBAA+B;EACnC,IAAI,UACF,OAAO,UAAU,UAAU,SAAS;EAEtC,OAAO,UAAU,UAAU,SAAS;;CAGtC,MAAM,eAAe,iBAAiB;CACtC,MAAM,cAAc,gBAAgB;CAGpC,MAAM,YAAY,cAAc,cAAc,MAAM,OAAO,YAAY,EAAE,CAAC,MAAM,OAAO,YAAY,CAAC;CACpG,MAAM,YAAY,cACV,cAAc,MAAM,OAAO,aAAa,EAC9C,CAAC,MAAM,OAAO,aAAa,CAC5B;CACD,MAAM,SAAS,cACP,cAAc,MAAM,OAAO,mBAAmB,EACpD,CAAC,MAAM,OAAO,mBAAmB,CAClC;CAGD,IAAI,CAAC,YAAY,CAAC,aAChB,OAAO;CAGT,OACE,qBAAA,UAAA,EAAA,UAAA,CACE,qBAAC,OAAD;EACE,eAAY;EACZ,MAAK;EACL,cAAW;EACX,cAAW;EACX,aAAU;EACV,OAAO;GACL,UAAU;GACV,KAAK;GACL,MAAM;GACN,OAAO;GACP,QAAQ;GACR,SAAS;GACT,YAAY;GACZ,gBAAgB;GAChB,iBAAiB,UAAU,UAAU,GAAG,OAAO,MAAM,GAAG,OAAO;GAC/D,QAAQ;GACR,WAAW,UAAU,UAAU,wBAAwB;GACxD;YAlBH,CAoBE,qBAAC,OAAD;GACE,OAAO;IACL,UAAU;IACV,YAAY;IACZ,OAAO,UAAU,UAAU,YAAY;IACvC,YAAY,MAAM,WAAW;IAC7B,YAAY,OAAO,UAAU,UAAU,SAAS,OAAO,GACrD,UAAU,UAAU,YAAY;IAElC,WACE,UAAU,UACN,wBACA,UAAU,aACV,iCACA,UAAU,UACV,wBACA;IACN,WAAW;IACX,YAAY;IACb;GACD,eAAY;aApBd;IAsBG,YAAY;IACb,oBAAC,MAAD,EAAM,CAAA;IACN,oBAAC,QAAD;KACE,OAAO,EACL,UAAU,aACX;eAEA,YAAY;KACR,CAAA;IACH;MAGL,YAAY,UAAU,WACrB,oBAAC,UAAD;GACE,SAAS;GACT,eAAY;GACZ,cAAW;GACX,OAAO;IACL,UAAU;IACV,QAAQ,WAAW,SAAS;IAC5B,SAAS,WAAW,cAAc;IAClC,UAAU,WAAW,SAAS;IAC9B,iBAAiB;IACjB,OAAO;IACP,QAAQ;IACR,cAAc;IACd,YAAY,MAAM,WAAW;IAC7B,YAAY;IACZ,QAAQ;IACR,YAAY;IACb;GACD,eAAe,MAAM;IACnB,EAAE,cAAc,MAAM,YAAY;IAClC,EAAE,cAAc,MAAM,YAAY,YAAY;;GAEhD,eAAe,MAAM;IACnB,EAAE,cAAc,MAAM,YAAY;IAClC,EAAE,cAAc,MAAM,YAAY;;GAEpC,UAAU,MAAM;IACd,EAAE,cAAc,MAAM,YAAY;IAClC,EAAE,cAAc,MAAM,YAAY,YAAY;IAC9C,EAAE,cAAc,MAAM,UAAU,aAAa;;GAE/C,SAAS,MAAM;IACb,EAAE,cAAc,MAAM,YAAY;IAClC,EAAE,cAAc,MAAM,YAAY;IAClC,EAAE,cAAc,MAAM,UAAU;;aAEnC;GAEQ,CAAA,CAEP;KAGN,oBAAC,SAAD,EAAA,UACG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAuDK,CAAA,CACP,EAAA,CAAA"}
1
+ {"version":3,"file":"MatchCountdown.js","names":[],"sources":["../../../../../../src/components/screens/combat/components/feedback/MatchCountdown.tsx"],"sourcesContent":["/**\n * MatchCountdown Component - Displays match start countdown sequence\n *\n * Korean: 매치 시작 카운트다운 (Match Start Countdown)\n *\n * Shows \"Ready?\" → \"3... 2... 1...\" → \"Fight!\" sequence with animations.\n * Implements Korean cyberpunk aesthetic with bilingual text support.\n * Plays audio cues for countdown and fight announcement.\n *\n * Refactored to use useKoreanTheme for consistent styling.\n *\n * @module components/combat/MatchCountdown\n * @category Combat UI\n */\n\nimport React, { useEffect, useMemo, useRef } from \"react\";\nimport { useAudio } from \"../../../../../audio/AudioProvider\";\nimport {\n MatchCountdownState,\n useMatchCountdown,\n} from \"../../../../../hooks/useMatchCountdown\";\nimport { useKoreanTheme } from \"../../../../shared/base/useKoreanTheme\";\nimport { hexColorToCSS } from \"../../../../../utils/colorUtils\";\n\n/**\n * Props for the MatchCountdown component\n */\nexport interface MatchCountdownProps {\n /** Callback when countdown completes */\n readonly onComplete: () => void;\n /** Whether layout should adapt for mobile screens */\n readonly isMobile: boolean;\n /** Optional callback for skip button */\n readonly onSkip?: () => void;\n /** Whether skip button should be shown */\n readonly showSkip?: boolean;\n}\n\n/**\n * Get display text for current countdown state\n */\nfunction getDisplayText(\n state: MatchCountdownState,\n currentNumber: number\n): {\n ko: string;\n en: string;\n} | null {\n switch (state) {\n case \"ready\":\n return { ko: \"준비?\", en: \"Ready?\" };\n case \"counting\":\n return { ko: String(currentNumber), en: String(currentNumber) };\n case \"fight\":\n return { ko: \"전투!\", en: \"Fight!\" };\n default:\n return null;\n }\n}\n\n/**\n * MatchCountdown Component\n *\n * Displays match start countdown with:\n * - \"Ready?\" announcement (1 second)\n * - Countdown from 3 to 1 (1 second intervals)\n * - \"Fight!\" announcement (1 second)\n * - Pulse/scale animations for emphasis\n * - Bilingual Korean-English text\n * - Audio cues for countdown and fight\n * - Optional skip button\n * - Responsive sizing for mobile/tablet/desktop\n *\n * Korean: 매치 시작 카운트다운 컴포넌트\n */\nconst COUNTDOWN_CONFIG = {\n readyDuration: 1,\n countdownInterval: 1,\n fightDuration: 1,\n startNumber: 3,\n} as const;\n\nexport const MatchCountdown: React.FC<MatchCountdownProps> = ({\n onComplete,\n isMobile,\n onSkip,\n showSkip = false,\n}) => {\n const audio = useAudio();\n const theme = useKoreanTheme({ variant: \"primary\", size: \"xlarge\", isMobile });\n\n const { state, currentNumber, startCountdown, skipCountdown, isActive } =\n useMatchCountdown(COUNTDOWN_CONFIG, onComplete);\n\n const hasStartedRef = useRef(false);\n\n useEffect(() => {\n if (!hasStartedRef.current) {\n hasStartedRef.current = true;\n startCountdown();\n }\n }, [startCountdown]);\n\n useEffect(() => {\n if (!audio.isAudioReady) return;\n\n if (state === \"counting\" && currentNumber > 0) {\n audio.playSFX(\"attack_light\"); // Using placeholder - will be countdown_beep\n } else if (state === \"fight\") {\n audio.playSFX(\"attack_heavy\"); // Using placeholder - will be fight_start\n }\n }, [state, currentNumber, audio]);\n\n const handleSkip = () => {\n skipCountdown();\n onSkip?.();\n };\n\n const displayText = getDisplayText(state, currentNumber);\n\n const getMainFontSize = (): string => {\n if (isMobile) {\n return state === \"fight\" ? \"72px\" : \"64px\";\n }\n return state === \"fight\" ? \"120px\" : \"96px\";\n };\n\n const getSubFontSize = (): string => {\n if (isMobile) {\n return state === \"fight\" ? \"48px\" : \"40px\";\n }\n return state === \"fight\" ? \"72px\" : \"56px\";\n };\n\n const mainFontSize = getMainFontSize();\n const subFontSize = getSubFontSize();\n\n const goldColor = useMemo(() => hexColorToCSS(theme.colors.ACCENT_GOLD), [theme.colors.ACCENT_GOLD]);\n const cyanColor = useMemo(\n () => hexColorToCSS(theme.colors.PRIMARY_CYAN),\n [theme.colors.PRIMARY_CYAN]\n );\n const darkBg = useMemo(\n () => hexColorToCSS(theme.colors.UI_BACKGROUND_DARK),\n [theme.colors.UI_BACKGROUND_DARK]\n );\n\n if (!isActive || !displayText) {\n return null;\n }\n\n return (\n <>\n <div\n data-testid=\"match-countdown\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label=\"Match countdown in progress\"\n aria-live=\"assertive\"\n style={{\n position: \"fixed\",\n top: 0,\n left: 0,\n width: \"100%\",\n height: \"100%\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n backgroundColor: state === \"fight\" ? `${darkBg}cc` : `${darkBg}ee`,\n zIndex: 1000,\n animation: state === \"ready\" ? \"fadeIn 0.3s ease-in\" : \"none\",\n }}\n >\n <div\n style={{\n fontSize: mainFontSize,\n fontWeight: \"bold\",\n color: state === \"fight\" ? goldColor : cyanColor,\n fontFamily: theme.fontFamily.KOREAN,\n textShadow: `0 0 ${state === \"fight\" ? \"40px\" : \"30px\"} ${\n state === \"fight\" ? goldColor : cyanColor\n }`,\n animation:\n state === \"ready\"\n ? \"pulse 0.8s ease-out\"\n : state === \"counting\"\n ? \"countdownPulse 0.8s ease-out\"\n : state === \"fight\"\n ? \"flash 0.3s ease-out\"\n : \"none\",\n textAlign: \"center\",\n userSelect: \"none\",\n }}\n data-testid=\"countdown-text\"\n >\n {displayText.ko}\n <br />\n <span\n style={{\n fontSize: subFontSize,\n }}\n >\n {displayText.en}\n </span>\n </div>\n\n {/* Optional Skip Button */}\n {showSkip && state !== \"fight\" && (\n <button\n onClick={handleSkip}\n data-testid=\"skip-countdown-button\"\n aria-label=\"Skip countdown\"\n style={{\n position: \"absolute\",\n bottom: isMobile ? \"40px\" : \"60px\",\n padding: isMobile ? \"10px 24px\" : \"12px 32px\",\n fontSize: isMobile ? \"14px\" : \"16px\",\n backgroundColor: cyanColor,\n color: darkBg,\n border: \"none\",\n borderRadius: \"6px\",\n fontFamily: theme.fontFamily.KOREAN,\n fontWeight: \"bold\",\n cursor: \"pointer\",\n transition: \"all 0.2s ease\",\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.transform = \"scale(1.05)\";\n e.currentTarget.style.boxShadow = `0 0 20px ${cyanColor}`;\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.transform = \"scale(1)\";\n e.currentTarget.style.boxShadow = \"none\";\n }}\n onFocus={(e) => {\n e.currentTarget.style.transform = \"scale(1.05)\";\n e.currentTarget.style.boxShadow = `0 0 20px ${cyanColor}`;\n e.currentTarget.style.outline = `2px solid ${cyanColor}`;\n }}\n onBlur={(e) => {\n e.currentTarget.style.transform = \"scale(1)\";\n e.currentTarget.style.boxShadow = \"none\";\n e.currentTarget.style.outline = \"none\";\n }}\n >\n 건너뛰기 | Skip\n </button>\n )}\n </div>\n\n {/* CSS Animations */}\n <style>\n {`\n @keyframes fadeIn {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n }\n\n @keyframes pulse {\n 0% {\n opacity: 0;\n transform: scale(0.9);\n }\n 50% {\n opacity: 1;\n transform: scale(1.05);\n }\n 100% {\n opacity: 1;\n transform: scale(1);\n }\n }\n\n @keyframes countdownPulse {\n 0% {\n opacity: 0;\n transform: scale(1.2);\n }\n 50% {\n opacity: 1;\n transform: scale(1.1);\n }\n 100% {\n opacity: 1;\n transform: scale(1);\n }\n }\n\n @keyframes flash {\n 0% {\n opacity: 0;\n transform: scale(1.5);\n }\n 30% {\n opacity: 1;\n transform: scale(1.3);\n }\n 100% {\n opacity: 1;\n transform: scale(1);\n }\n }\n `}\n </style>\n </>\n );\n};\n\nexport default MatchCountdown;\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"RoundAnnouncementOverlayHtml.d.ts","sourceRoot":"","sources":["../../../../../../src/components/screens/combat/components/feedback/RoundAnnouncementOverlayHtml.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAMN,MAAM,OAAO,CAAC;AACf,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAIrD;;;;GAIG;AACH,MAAM,WAAW,UAAU;IACzB,mCAAmC;IACnC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,yCAAyC;IACzC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,oCAAoC;IACpC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,iCAAiC;IACjC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,qCAAqC;IACrC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,gDAAgD;IAChD,QAAQ,CAAC,WAAW,EAAE,WAAW,GAAG,IAAI,CAAC;IACzC,uDAAuD;IACvD,QAAQ,CAAC,YAAY,EAAE;QAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9E,kCAAkC;IAClC,QAAQ,CAAC,UAAU,CAAC,EAAE,UAAU,CAAC;IACjC,wCAAwC;IACxC,QAAQ,CAAC,mBAAmB,EAAE,MAAM,IAAI,CAAC;IACzC,2CAA2C;IAC3C,QAAQ,CAAC,MAAM,EAAE,MAAM,IAAI,CAAC;IAC5B,qDAAqD;IACrD,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,kEAAkE;IAClE,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,oCAAoC;IACpC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;CACrC;AAED;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,iBAAiB,EAAE,KAAK,CAAC,EAAE,CAAC,sBAAsB,CA2R9D,CAAC;AAEF,eAAe,iBAAiB,CAAC"}
1
+ {"version":3,"file":"RoundAnnouncementOverlayHtml.d.ts","sourceRoot":"","sources":["../../../../../../src/components/screens/combat/components/feedback/RoundAnnouncementOverlayHtml.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAMN,MAAM,OAAO,CAAC;AACf,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAIrD;;;;GAIG;AACH,MAAM,WAAW,UAAU;IACzB,mCAAmC;IACnC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,yCAAyC;IACzC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,oCAAoC;IACpC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,iCAAiC;IACjC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,qCAAqC;IACrC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,gDAAgD;IAChD,QAAQ,CAAC,WAAW,EAAE,WAAW,GAAG,IAAI,CAAC;IACzC,uDAAuD;IACvD,QAAQ,CAAC,YAAY,EAAE;QAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9E,kCAAkC;IAClC,QAAQ,CAAC,UAAU,CAAC,EAAE,UAAU,CAAC;IACjC,wCAAwC;IACxC,QAAQ,CAAC,mBAAmB,EAAE,MAAM,IAAI,CAAC;IACzC,2CAA2C;IAC3C,QAAQ,CAAC,MAAM,EAAE,MAAM,IAAI,CAAC;IAC5B,qDAAqD;IACrD,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,kEAAkE;IAClE,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,oCAAoC;IACpC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;CACrC;AAED;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,iBAAiB,EAAE,KAAK,CAAC,EAAE,CAAC,sBAAsB,CAkR9D,CAAC;AAEF,eAAe,iBAAiB,CAAC"}