blacktrigram 0.7.19 → 0.7.20
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.
- package/README.md +2 -2
- package/lib/components/screens/combat/CombatScreen3D.d.ts +0 -4
- package/lib/components/screens/combat/CombatScreen3D.d.ts.map +1 -1
- package/lib/components/screens/combat/CombatScreen3D.js +262 -268
- package/lib/components/screens/combat/CombatScreen3D.js.map +1 -1
- package/lib/components/screens/intro/IntroScreen3D.js +1 -1
- package/lib/components/screens/training/TrainingScreen3D.d.ts.map +1 -1
- package/lib/components/screens/training/TrainingScreen3D.js.map +1 -1
- package/lib/components/shared/three/effects/ThunderEffect3D.d.ts.map +1 -1
- package/lib/components/shared/ui/SplashScreen.js +2 -2
- package/lib/hooks/usePlayerAnimation.d.ts.map +1 -1
- package/lib/hooks/usePlayerAnimation.js +37 -50
- package/lib/hooks/usePlayerAnimation.js.map +1 -1
- package/lib/utils/inputSystem.d.ts.map +1 -1
- package/lib/utils/inputSystem.js +1 -1
- package/lib/utils/inputSystem.js.map +1 -1
- package/package.json +9 -7
package/README.md
CHANGED
|
@@ -184,7 +184,7 @@ Built for **combat realism** and **authentic simulation**:
|
|
|
184
184
|
|
|
185
185
|
### 🎮 Rendering Engine
|
|
186
186
|
|
|
187
|
-

|
|
188
188
|

|
|
189
189
|

|
|
190
190
|

|
|
@@ -380,7 +380,7 @@ George Dorn provides detailed repository deep-dives based on actual code inspect
|
|
|
380
380
|
|
|
381
381
|
**[Repository Deep-Dive](https://hack23.com/blog-george-dorn-trigram-code.html)**
|
|
382
382
|
|
|
383
|
-
**Stack:** TypeScript 6.0, React 19, Three.js 0.
|
|
383
|
+
**Stack:** TypeScript 6.0, React 19, Three.js 0.184, Vite 8
|
|
384
384
|
**Metrics:** 132 TypeScript files, 70 vital points system, 5 fighter archetypes
|
|
385
385
|
|
|
386
386
|
Examined package.json dependencies, explored src/ structure, verified combat system implementation, and reviewed AI integrations.
|
|
@@ -65,10 +65,6 @@ export interface CombatScreen3DProps {
|
|
|
65
65
|
*/
|
|
66
66
|
readonly showPerformanceOverlay?: boolean;
|
|
67
67
|
}
|
|
68
|
-
/**
|
|
69
|
-
* CombatScreen3D Component
|
|
70
|
-
* Three.js-based combat screen with 3D characters and effects
|
|
71
|
-
*/
|
|
72
68
|
export declare const CombatScreen3D: React.FC<CombatScreen3DProps>;
|
|
73
69
|
export default CombatScreen3D;
|
|
74
70
|
//# sourceMappingURL=CombatScreen3D.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CombatScreen3D.d.ts","sourceRoot":"","sources":["../../../../src/components/screens/combat/CombatScreen3D.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAUH,OAAO,KAMN,MAAM,OAAO,CAAC;AAUf,OAAO,EAAa,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAsB1D,OAAO,EAEL,QAAQ,EAIT,MAAM,gBAAgB,CAAC;AAkFxB;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC;;;OAGG;IACH,QAAQ,CAAC,OAAO,EAAE,SAAS,WAAW,EAAE,CAAC;IACzC;;;;OAIG;IACH,QAAQ,CAAC,cAAc,EAAE,CACvB,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,OAAO,CAAC,WAAW,CAAC,KAC1B,IAAI,CAAC;IACV;;OAEG;IACH,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B;;OAEG;IACH,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B;;OAEG;IACH,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B;;OAEG;IACH,QAAQ,CAAC,cAAc,EAAE,MAAM,IAAI,CAAC;IACpC;;;OAGG;IACH,QAAQ,CAAC,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7C;;OAEG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC;IAC7B;;OAEG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB;;OAEG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB;;OAEG;IACH,QAAQ,CAAC,qBAAqB,CAAC,EAAE,OAAO,CAAC;IACzC;;OAEG;IACH,QAAQ,CAAC,sBAAsB,CAAC,EAAE,OAAO,CAAC;CAC3C;
|
|
1
|
+
{"version":3,"file":"CombatScreen3D.d.ts","sourceRoot":"","sources":["../../../../src/components/screens/combat/CombatScreen3D.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAUH,OAAO,KAMN,MAAM,OAAO,CAAC;AAUf,OAAO,EAAa,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAsB1D,OAAO,EAEL,QAAQ,EAIT,MAAM,gBAAgB,CAAC;AAkFxB;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC;;;OAGG;IACH,QAAQ,CAAC,OAAO,EAAE,SAAS,WAAW,EAAE,CAAC;IACzC;;;;OAIG;IACH,QAAQ,CAAC,cAAc,EAAE,CACvB,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,OAAO,CAAC,WAAW,CAAC,KAC1B,IAAI,CAAC;IACV;;OAEG;IACH,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B;;OAEG;IACH,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B;;OAEG;IACH,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B;;OAEG;IACH,QAAQ,CAAC,cAAc,EAAE,MAAM,IAAI,CAAC;IACpC;;;OAGG;IACH,QAAQ,CAAC,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7C;;OAEG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC;IAC7B;;OAEG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB;;OAEG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB;;OAEG;IACH,QAAQ,CAAC,qBAAqB,CAAC,EAAE,OAAO,CAAC;IACzC;;OAEG;IACH,QAAQ,CAAC,sBAAsB,CAAC,EAAE,OAAO,CAAC;CAC3C;AAgCD,eAAO,MAAM,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CA0+FxD,CAAC;AAEF,eAAe,cAAc,CAAC"}
|
|
@@ -90,6 +90,18 @@ import { Bloom, EffectComposer, Noise, Vignette } from "@react-three/postprocess
|
|
|
90
90
|
* CombatScreen3D Component
|
|
91
91
|
* Three.js-based combat screen with 3D characters and effects
|
|
92
92
|
*/
|
|
93
|
+
/**
|
|
94
|
+
* AdaptiveQualityWrapper - Internal component to use adaptive quality hook
|
|
95
|
+
* Must be inside Canvas to use useFrame from @react-three/fiber
|
|
96
|
+
*
|
|
97
|
+
* Hoisted outside CombatScreen3D to avoid "Cannot create components during render"
|
|
98
|
+
* warnings from react-hooks/component-creation. Keeps the component type stable
|
|
99
|
+
* across renders of the parent.
|
|
100
|
+
*/
|
|
101
|
+
var AdaptiveQualityWrapper = ({ enabled, isMobile, children }) => {
|
|
102
|
+
useAdaptiveQuality(enabled, isMobile, (newQuality) => {});
|
|
103
|
+
return /* @__PURE__ */ jsx(Fragment, { children });
|
|
104
|
+
};
|
|
93
105
|
var CombatScreen3D = ({ players, onPlayerUpdate, currentRound, timeRemaining, isPaused, onReturnToMenu, onGameEnd, width = 1200, height = 800, enableAdaptiveQuality, showPerformanceOverlay = false }) => {
|
|
94
106
|
const [contentReady, setContentReady] = useState(false);
|
|
95
107
|
const contextLossCountRef = useRef(0);
|
|
@@ -150,22 +162,6 @@ var CombatScreen3D = ({ players, onPlayerUpdate, currentRound, timeRemaining, is
|
|
|
150
162
|
};
|
|
151
163
|
}, [isMobile, width]);
|
|
152
164
|
const shouldEnableAdaptiveQuality = enableAdaptiveQuality ?? isMobile;
|
|
153
|
-
/**
|
|
154
|
-
* AdaptiveQualityWrapper - Internal component to use adaptive quality hook
|
|
155
|
-
* Must be inside Canvas to use useFrame from @react-three/fiber
|
|
156
|
-
*
|
|
157
|
-
* Memoized with useMemo so the component type is stable across renders.
|
|
158
|
-
* Note: renderConfig is intentionally NOT in dependencies to prevent
|
|
159
|
-
* component recreation when performance settings change, which would
|
|
160
|
-
* reset the internal state of useAdaptiveQuality hook.
|
|
161
|
-
*/
|
|
162
|
-
const AdaptiveQualityWrapper = useMemo(() => {
|
|
163
|
-
const Component = ({ children }) => {
|
|
164
|
-
useAdaptiveQuality(shouldEnableAdaptiveQuality, isMobile, (newQuality) => {});
|
|
165
|
-
return /* @__PURE__ */ jsx(Fragment, { children });
|
|
166
|
-
};
|
|
167
|
-
return Component;
|
|
168
|
-
}, [shouldEnableAdaptiveQuality, isMobile]);
|
|
169
165
|
const { state: combatState, actions: combatActions } = useCombatState();
|
|
170
166
|
const [overlayVisible, setOverlayVisible] = useState(false);
|
|
171
167
|
const [severityFilters, setSeverityFilters] = useState([]);
|
|
@@ -210,7 +206,7 @@ var CombatScreen3D = ({ players, onPlayerUpdate, currentRound, timeRemaining, is
|
|
|
210
206
|
setTimeout(() => setMatchScore(newScore), 0);
|
|
211
207
|
}, []);
|
|
212
208
|
const [internalRound, setInternalRound] = useState(currentRound);
|
|
213
|
-
const [currentTime, setCurrentTime] = useState(Date.now());
|
|
209
|
+
const [currentTime, setCurrentTime] = useState(() => Date.now());
|
|
214
210
|
const [hasShownMatchCountdown, setHasShownMatchCountdown] = useState(true);
|
|
215
211
|
const [showMatchCountdown, setShowMatchCountdown] = useState(false);
|
|
216
212
|
const [showRoundStart, setShowRoundStart] = useState(false);
|
|
@@ -361,7 +357,6 @@ var CombatScreen3D = ({ players, onPlayerUpdate, currentRound, timeRemaining, is
|
|
|
361
357
|
playerPositions[1].y
|
|
362
358
|
];
|
|
363
359
|
}, [playerPositions]);
|
|
364
|
-
const player1LastRotationRef = useRef(0);
|
|
365
360
|
const player2Rotation = useMemo(() => {
|
|
366
361
|
const dx = player1Position3D[0] - player2Position3D[0];
|
|
367
362
|
const dz = player1Position3D[2] - player2Position3D[2];
|
|
@@ -483,16 +478,11 @@ var CombatScreen3D = ({ players, onPlayerUpdate, currentRound, timeRemaining, is
|
|
|
483
478
|
accelerationOverride: player1SpeedModifiers.finalAcceleration
|
|
484
479
|
});
|
|
485
480
|
const player1Rotation = useMemo(() => {
|
|
486
|
-
if (player1IsMoving && player1Velocity && (player1Velocity.x !== 0 || player1Velocity.y !== 0))
|
|
487
|
-
|
|
488
|
-
player1LastRotationRef.current = movementRotation;
|
|
489
|
-
return movementRotation;
|
|
490
|
-
} else {
|
|
481
|
+
if (player1IsMoving && player1Velocity && (player1Velocity.x !== 0 || player1Velocity.y !== 0)) return Math.atan2(player1Velocity.x, player1Velocity.y);
|
|
482
|
+
else {
|
|
491
483
|
const dx = player2Position3D[0] - player1Position3D[0];
|
|
492
484
|
const dz = player2Position3D[2] - player1Position3D[2];
|
|
493
|
-
|
|
494
|
-
player1LastRotationRef.current = targetRotation;
|
|
495
|
-
return targetRotation;
|
|
485
|
+
return Math.atan2(dx, dz);
|
|
496
486
|
}
|
|
497
487
|
}, [
|
|
498
488
|
player1IsMoving,
|
|
@@ -505,8 +495,8 @@ var CombatScreen3D = ({ players, onPlayerUpdate, currentRound, timeRemaining, is
|
|
|
505
495
|
const validPlayersRefForAnimation = useRef(null);
|
|
506
496
|
const player1HitTriggerFrameRef = useRef(6);
|
|
507
497
|
const player1AttackHitFiredRef = useRef(false);
|
|
508
|
-
const
|
|
509
|
-
const
|
|
498
|
+
const [player1AttackDuration, setPlayer1AttackDuration] = useState(.55);
|
|
499
|
+
const [player2AttackDuration, setPlayer2AttackDuration] = useState(.55);
|
|
510
500
|
const clearPlayer1AttackAnimation = useRef(() => {
|
|
511
501
|
setPlayer1AttackAnimation(void 0);
|
|
512
502
|
setPlayer1TechniqueId(void 0);
|
|
@@ -616,12 +606,12 @@ var CombatScreen3D = ({ players, onPlayerUpdate, currentRound, timeRemaining, is
|
|
|
616
606
|
player1AnimationType: getTechniqueAnimationType(player1TechniqueId),
|
|
617
607
|
player1Stance: player1Data.currentStance,
|
|
618
608
|
player1BasePosition: player1Position3D,
|
|
619
|
-
player1AnimationDuration:
|
|
609
|
+
player1AnimationDuration: player1AttackDuration,
|
|
620
610
|
player2Attacking: player2Animation.currentState === AnimationState.ATTACK,
|
|
621
611
|
player2AnimationType: getTechniqueAnimationType(player2TechniqueId),
|
|
622
612
|
player2Stance: validPlayers[1].currentStance,
|
|
623
613
|
player2BasePosition: player2Position3D,
|
|
624
|
-
player2AnimationDuration:
|
|
614
|
+
player2AnimationDuration: player2AttackDuration
|
|
625
615
|
});
|
|
626
616
|
const [player1LocalStance, setPlayer1LocalStance] = useState(validPlayers[0].currentStance);
|
|
627
617
|
useEffect(() => {
|
|
@@ -818,7 +808,7 @@ var CombatScreen3D = ({ players, onPlayerUpdate, currentRound, timeRemaining, is
|
|
|
818
808
|
const attackFrames = Math.max(1, Math.round(attackDuration * 60));
|
|
819
809
|
player1HitTriggerFrameRef.current = Math.round(attackFrames * .4);
|
|
820
810
|
player1AttackHitFiredRef.current = false;
|
|
821
|
-
|
|
811
|
+
setPlayer1AttackDuration(attackDuration);
|
|
822
812
|
player1Animation.transitionToAttack(attackDuration);
|
|
823
813
|
combatActions.setExecutingTechnique(true);
|
|
824
814
|
onPlayerUpdate(0, {
|
|
@@ -1193,13 +1183,13 @@ var CombatScreen3D = ({ players, onPlayerUpdate, currentRound, timeRemaining, is
|
|
|
1193
1183
|
setPlayer2AttackAnimation(p2AttackAnimName);
|
|
1194
1184
|
if (selectedTechnique.id) setPlayer2TechniqueId(selectedTechnique.id);
|
|
1195
1185
|
const p2AttackDur = getAnimation(p2AttackAnimName)?.duration ?? .55;
|
|
1196
|
-
|
|
1186
|
+
setPlayer2AttackDuration(p2AttackDur);
|
|
1197
1187
|
player2Animation.transitionToAttack(p2AttackDur);
|
|
1198
1188
|
} else {
|
|
1199
1189
|
setPlayer2AttackAnimation(aiFallbackAnim);
|
|
1200
1190
|
if (aiFallbackTechnique?.id) setPlayer2TechniqueId(aiFallbackTechnique.id);
|
|
1201
1191
|
const p2FallbackDur = getAnimation(aiFallbackAnim)?.duration ?? .55;
|
|
1202
|
-
|
|
1192
|
+
setPlayer2AttackDuration(p2FallbackDur);
|
|
1203
1193
|
player2Animation.transitionToAttack(p2FallbackDur);
|
|
1204
1194
|
}
|
|
1205
1195
|
handleAIAttack(selectedTechnique, targetVitalPoint);
|
|
@@ -1215,13 +1205,13 @@ var CombatScreen3D = ({ players, onPlayerUpdate, currentRound, timeRemaining, is
|
|
|
1215
1205
|
setPlayer2AttackAnimation(p2TechAnimName);
|
|
1216
1206
|
if (selectedTechnique.id) setPlayer2TechniqueId(selectedTechnique.id);
|
|
1217
1207
|
const p2TechDur = getAnimation(p2TechAnimName)?.duration ?? .6;
|
|
1218
|
-
|
|
1208
|
+
setPlayer2AttackDuration(p2TechDur);
|
|
1219
1209
|
player2Animation.transitionToAttack(p2TechDur);
|
|
1220
1210
|
} else {
|
|
1221
1211
|
setPlayer2AttackAnimation(aiFallbackAnim);
|
|
1222
1212
|
if (aiFallbackTechnique?.id) setPlayer2TechniqueId(aiFallbackTechnique.id);
|
|
1223
1213
|
const p2FallbackDur = getAnimation(aiFallbackAnim)?.duration ?? .6;
|
|
1224
|
-
|
|
1214
|
+
setPlayer2AttackDuration(p2FallbackDur);
|
|
1225
1215
|
player2Animation.transitionToAttack(p2FallbackDur);
|
|
1226
1216
|
}
|
|
1227
1217
|
handleAITechnique(selectedTechnique, targetVitalPoint);
|
|
@@ -1264,13 +1254,13 @@ var CombatScreen3D = ({ players, onPlayerUpdate, currentRound, timeRemaining, is
|
|
|
1264
1254
|
setPlayer2AttackAnimation(p2CounterAnimName);
|
|
1265
1255
|
if (selectedTechnique.id) setPlayer2TechniqueId(selectedTechnique.id);
|
|
1266
1256
|
const p2CounterDur = getAnimation(p2CounterAnimName)?.duration ?? .6;
|
|
1267
|
-
|
|
1257
|
+
setPlayer2AttackDuration(p2CounterDur);
|
|
1268
1258
|
player2Animation.transitionToAttack(p2CounterDur);
|
|
1269
1259
|
} else {
|
|
1270
1260
|
setPlayer2AttackAnimation(aiFallbackAnim);
|
|
1271
1261
|
if (aiFallbackTechnique?.id) setPlayer2TechniqueId(aiFallbackTechnique.id);
|
|
1272
1262
|
const p2FallbackDur = getAnimation(aiFallbackAnim)?.duration ?? .6;
|
|
1273
|
-
|
|
1263
|
+
setPlayer2AttackDuration(p2FallbackDur);
|
|
1274
1264
|
player2Animation.transitionToAttack(p2FallbackDur);
|
|
1275
1265
|
}
|
|
1276
1266
|
handleAIAttack(selectedTechnique, targetVitalPoint);
|
|
@@ -1478,245 +1468,249 @@ var CombatScreen3D = ({ players, onPlayerUpdate, currentRound, timeRemaining, is
|
|
|
1478
1468
|
],
|
|
1479
1469
|
intensity: 1.2
|
|
1480
1470
|
}),
|
|
1481
|
-
/* @__PURE__ */ jsxs(AdaptiveQualityWrapper, {
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1471
|
+
/* @__PURE__ */ jsxs(AdaptiveQualityWrapper, {
|
|
1472
|
+
enabled: shouldEnableAdaptiveQuality,
|
|
1473
|
+
isMobile,
|
|
1474
|
+
children: [
|
|
1475
|
+
showPerformanceOverlay && !showPerformanceMonitor && /* @__PURE__ */ jsx(PerformanceOverlay3D, {}),
|
|
1476
|
+
/* @__PURE__ */ jsx(CombatArena3D, {
|
|
1477
|
+
lighting: "cyberpunk",
|
|
1478
|
+
scale: arenaBounds.scale,
|
|
1479
|
+
worldWidthMeters: arenaBounds.worldWidthMeters,
|
|
1480
|
+
worldDepthMeters: arenaBounds.worldDepthMeters
|
|
1481
|
+
}),
|
|
1482
|
+
/* @__PURE__ */ jsx(AnimationUpdater, {
|
|
1483
|
+
player1Animation,
|
|
1484
|
+
player2Animation
|
|
1485
|
+
}),
|
|
1486
|
+
/* @__PURE__ */ jsx(AccelerationUpdater, {
|
|
1487
|
+
isMoving: player1IsMoving,
|
|
1488
|
+
velocity: player1Velocity,
|
|
1489
|
+
movementTimeRef: player1MovementTimeRef,
|
|
1490
|
+
lastDirectionRef: player1LastDirectionRef,
|
|
1491
|
+
onSpeedUpdate: setPlayer1AccelerationBasedSpeed,
|
|
1492
|
+
walkSpeed: player1WalkRunSpeeds.walkSpeed,
|
|
1493
|
+
runSpeed: player1WalkRunSpeeds.runSpeed
|
|
1494
|
+
}),
|
|
1495
|
+
/* @__PURE__ */ jsx(Player3DWithTransitions, {
|
|
1496
|
+
...convertPlayerStateToProps(validPlayers[0], player1PositionWithAttackMovement, player1Rotation, {
|
|
1497
|
+
isMobile,
|
|
1498
|
+
facing: "right",
|
|
1499
|
+
enableFacialExpressions: true,
|
|
1500
|
+
enableEyeTracking: true,
|
|
1501
|
+
opponentPosition: player2PositionWithAttackMovement
|
|
1502
|
+
}),
|
|
1503
|
+
currentAnimation: animationStateToPlayerAnimation(player1Animation.currentState),
|
|
1504
|
+
attackAnimation: player1AttackAnimation,
|
|
1505
|
+
laterality: combatState.playerLaterality[0],
|
|
1506
|
+
enableTransitionEffects: !isMobile,
|
|
1507
|
+
enableStanceSymbol: !isMobile,
|
|
1508
|
+
enableStanceAudio: true
|
|
1509
|
+
}),
|
|
1510
|
+
/* @__PURE__ */ jsx(Player3DWithTransitions, {
|
|
1511
|
+
...convertPlayerStateToProps(validPlayers[1], player2PositionWithAttackMovement, player2Rotation, {
|
|
1512
|
+
isMobile,
|
|
1513
|
+
facing: "right",
|
|
1514
|
+
enableFacialExpressions: true,
|
|
1515
|
+
enableEyeTracking: true,
|
|
1516
|
+
opponentPosition: player1PositionWithAttackMovement
|
|
1517
|
+
}),
|
|
1518
|
+
currentAnimation: animationStateToPlayerAnimation(player2Animation.currentState),
|
|
1519
|
+
attackAnimation: player2AttackAnimation,
|
|
1520
|
+
laterality: combatState.playerLaterality[1],
|
|
1521
|
+
enableTransitionEffects: !isMobile,
|
|
1522
|
+
enableStanceSymbol: !isMobile,
|
|
1523
|
+
enableStanceAudio: true
|
|
1524
|
+
}),
|
|
1525
|
+
(player1MovementState.isLimping || player1MovementState.isSevereLimp) && /* @__PURE__ */ jsx(Html, {
|
|
1526
|
+
position: [
|
|
1527
|
+
player1Position3D[0],
|
|
1528
|
+
player1Position3D[1] + 2.5,
|
|
1529
|
+
player1Position3D[2]
|
|
1530
|
+
],
|
|
1531
|
+
center: true,
|
|
1532
|
+
"data-testid": "player1-movement-status",
|
|
1533
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
1534
|
+
style: {
|
|
1535
|
+
fontSize: isMobile ? "12px" : "14px",
|
|
1536
|
+
color: player1MovementState.isSevereLimp ? toHexColor(KOREAN_COLORS.TEXT_ERROR) : toHexColor(KOREAN_COLORS.ACCENT_GOLD),
|
|
1537
|
+
fontFamily: FONT_FAMILY.KOREAN,
|
|
1538
|
+
fontWeight: "bold",
|
|
1539
|
+
textShadow: "0 0 4px rgba(0,0,0,0.8)",
|
|
1540
|
+
background: "rgba(0, 0, 0, 0.6)",
|
|
1541
|
+
padding: "4px 8px",
|
|
1542
|
+
borderRadius: "4px",
|
|
1543
|
+
whiteSpace: "nowrap"
|
|
1544
|
+
},
|
|
1545
|
+
children: [
|
|
1546
|
+
player1MovementState.statusText.korean,
|
|
1547
|
+
" |",
|
|
1548
|
+
" ",
|
|
1549
|
+
player1MovementState.statusText.english
|
|
1550
|
+
]
|
|
1551
|
+
})
|
|
1552
|
+
}),
|
|
1553
|
+
(player2MovementState.isLimping || player2MovementState.isSevereLimp) && /* @__PURE__ */ jsx(Html, {
|
|
1554
|
+
position: [
|
|
1555
|
+
player2Position3D[0],
|
|
1556
|
+
player2Position3D[1] + 2.5,
|
|
1557
|
+
player2Position3D[2]
|
|
1558
|
+
],
|
|
1559
|
+
center: true,
|
|
1560
|
+
"data-testid": "player2-movement-status",
|
|
1561
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
1562
|
+
style: {
|
|
1563
|
+
fontSize: isMobile ? "12px" : "14px",
|
|
1564
|
+
color: player2MovementState.isSevereLimp ? toHexColor(KOREAN_COLORS.TEXT_ERROR) : toHexColor(KOREAN_COLORS.ACCENT_GOLD),
|
|
1565
|
+
fontFamily: FONT_FAMILY.KOREAN,
|
|
1566
|
+
fontWeight: "bold",
|
|
1567
|
+
textShadow: "0 0 4px rgba(0,0,0,0.8)",
|
|
1568
|
+
background: "rgba(0, 0, 0, 0.6)",
|
|
1569
|
+
padding: "4px 8px",
|
|
1570
|
+
borderRadius: "4px",
|
|
1571
|
+
whiteSpace: "nowrap"
|
|
1572
|
+
},
|
|
1573
|
+
children: [
|
|
1574
|
+
player2MovementState.statusText.korean,
|
|
1575
|
+
" |",
|
|
1576
|
+
" ",
|
|
1577
|
+
player2MovementState.statusText.english
|
|
1578
|
+
]
|
|
1579
|
+
})
|
|
1580
|
+
}),
|
|
1581
|
+
/* @__PURE__ */ jsx(TraumaOverlay3D, {
|
|
1582
|
+
playerId: "player",
|
|
1583
|
+
health: validPlayers[0].health,
|
|
1584
|
+
injuries: player1Injuries,
|
|
1585
|
+
characterPosition: player1Position3D,
|
|
1504
1586
|
isMobile,
|
|
1505
|
-
|
|
1506
|
-
enableFacialExpressions: true,
|
|
1507
|
-
enableEyeTracking: true,
|
|
1508
|
-
opponentPosition: player2PositionWithAttackMovement
|
|
1587
|
+
showFractures: true
|
|
1509
1588
|
}),
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
enableStanceAudio: true
|
|
1516
|
-
}),
|
|
1517
|
-
/* @__PURE__ */ jsx(Player3DWithTransitions, {
|
|
1518
|
-
...convertPlayerStateToProps(validPlayers[1], player2PositionWithAttackMovement, player2Rotation, {
|
|
1589
|
+
/* @__PURE__ */ jsx(TraumaOverlay3D, {
|
|
1590
|
+
playerId: "enemy",
|
|
1591
|
+
health: validPlayers[1].health,
|
|
1592
|
+
injuries: player2Injuries,
|
|
1593
|
+
characterPosition: player2Position3D,
|
|
1519
1594
|
isMobile,
|
|
1520
|
-
|
|
1521
|
-
enableFacialExpressions: true,
|
|
1522
|
-
enableEyeTracking: true,
|
|
1523
|
-
opponentPosition: player1PositionWithAttackMovement
|
|
1595
|
+
showFractures: true
|
|
1524
1596
|
}),
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
player1Position3D[0],
|
|
1535
|
-
player1Position3D[1] + 2.5,
|
|
1536
|
-
player1Position3D[2]
|
|
1537
|
-
],
|
|
1538
|
-
center: true,
|
|
1539
|
-
"data-testid": "player1-movement-status",
|
|
1540
|
-
children: /* @__PURE__ */ jsxs("div", {
|
|
1541
|
-
style: {
|
|
1542
|
-
fontSize: isMobile ? "12px" : "14px",
|
|
1543
|
-
color: player1MovementState.isSevereLimp ? toHexColor(KOREAN_COLORS.TEXT_ERROR) : toHexColor(KOREAN_COLORS.ACCENT_GOLD),
|
|
1544
|
-
fontFamily: FONT_FAMILY.KOREAN,
|
|
1545
|
-
fontWeight: "bold",
|
|
1546
|
-
textShadow: "0 0 4px rgba(0,0,0,0.8)",
|
|
1547
|
-
background: "rgba(0, 0, 0, 0.6)",
|
|
1548
|
-
padding: "4px 8px",
|
|
1549
|
-
borderRadius: "4px",
|
|
1550
|
-
whiteSpace: "nowrap"
|
|
1551
|
-
},
|
|
1552
|
-
children: [
|
|
1553
|
-
player1MovementState.statusText.korean,
|
|
1554
|
-
" |",
|
|
1555
|
-
" ",
|
|
1556
|
-
player1MovementState.statusText.english
|
|
1557
|
-
]
|
|
1558
|
-
})
|
|
1559
|
-
}),
|
|
1560
|
-
(player2MovementState.isLimping || player2MovementState.isSevereLimp) && /* @__PURE__ */ jsx(Html, {
|
|
1561
|
-
position: [
|
|
1562
|
-
player2Position3D[0],
|
|
1563
|
-
player2Position3D[1] + 2.5,
|
|
1564
|
-
player2Position3D[2]
|
|
1565
|
-
],
|
|
1566
|
-
center: true,
|
|
1567
|
-
"data-testid": "player2-movement-status",
|
|
1568
|
-
children: /* @__PURE__ */ jsxs("div", {
|
|
1569
|
-
style: {
|
|
1570
|
-
fontSize: isMobile ? "12px" : "14px",
|
|
1571
|
-
color: player2MovementState.isSevereLimp ? toHexColor(KOREAN_COLORS.TEXT_ERROR) : toHexColor(KOREAN_COLORS.ACCENT_GOLD),
|
|
1572
|
-
fontFamily: FONT_FAMILY.KOREAN,
|
|
1573
|
-
fontWeight: "bold",
|
|
1574
|
-
textShadow: "0 0 4px rgba(0,0,0,0.8)",
|
|
1575
|
-
background: "rgba(0, 0, 0, 0.6)",
|
|
1576
|
-
padding: "4px 8px",
|
|
1577
|
-
borderRadius: "4px",
|
|
1578
|
-
whiteSpace: "nowrap"
|
|
1579
|
-
},
|
|
1580
|
-
children: [
|
|
1581
|
-
player2MovementState.statusText.korean,
|
|
1582
|
-
" |",
|
|
1583
|
-
" ",
|
|
1584
|
-
player2MovementState.statusText.english
|
|
1585
|
-
]
|
|
1586
|
-
})
|
|
1587
|
-
}),
|
|
1588
|
-
/* @__PURE__ */ jsx(TraumaOverlay3D, {
|
|
1589
|
-
playerId: "player",
|
|
1590
|
-
health: validPlayers[0].health,
|
|
1591
|
-
injuries: player1Injuries,
|
|
1592
|
-
characterPosition: player1Position3D,
|
|
1593
|
-
isMobile,
|
|
1594
|
-
showFractures: true
|
|
1595
|
-
}),
|
|
1596
|
-
/* @__PURE__ */ jsx(TraumaOverlay3D, {
|
|
1597
|
-
playerId: "enemy",
|
|
1598
|
-
health: validPlayers[1].health,
|
|
1599
|
-
injuries: player2Injuries,
|
|
1600
|
-
characterPosition: player2Position3D,
|
|
1601
|
-
isMobile,
|
|
1602
|
-
showFractures: true
|
|
1603
|
-
}),
|
|
1604
|
-
/* @__PURE__ */ jsx(HitEffects3D, {
|
|
1605
|
-
effects: combatState.hitEffects,
|
|
1606
|
-
onEffectComplete: handleEffectComplete,
|
|
1607
|
-
arenaBounds
|
|
1608
|
-
}),
|
|
1609
|
-
/* @__PURE__ */ jsx(CombatParticleEffects3D, {
|
|
1610
|
-
hitEffects: combatState.hitEffects,
|
|
1611
|
-
enabled: true,
|
|
1612
|
-
isMobile
|
|
1613
|
-
}),
|
|
1614
|
-
overlayVisible && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1615
|
-
/* @__PURE__ */ jsx(VitalPointMarkers3D, {
|
|
1616
|
-
position: player1Position3D,
|
|
1617
|
-
visible: overlayVisible,
|
|
1618
|
-
severityFilter: severityFilters,
|
|
1619
|
-
regionFilter,
|
|
1620
|
-
searchQuery,
|
|
1621
|
-
showLabels,
|
|
1622
|
-
scale,
|
|
1623
|
-
animated,
|
|
1624
|
-
onPointClick: () => {}
|
|
1597
|
+
/* @__PURE__ */ jsx(HitEffects3D, {
|
|
1598
|
+
effects: combatState.hitEffects,
|
|
1599
|
+
onEffectComplete: handleEffectComplete,
|
|
1600
|
+
arenaBounds
|
|
1601
|
+
}),
|
|
1602
|
+
/* @__PURE__ */ jsx(CombatParticleEffects3D, {
|
|
1603
|
+
hitEffects: combatState.hitEffects,
|
|
1604
|
+
enabled: true,
|
|
1605
|
+
isMobile
|
|
1625
1606
|
}),
|
|
1626
|
-
/* @__PURE__ */
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1607
|
+
overlayVisible && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1608
|
+
/* @__PURE__ */ jsx(VitalPointMarkers3D, {
|
|
1609
|
+
position: player1Position3D,
|
|
1610
|
+
visible: overlayVisible,
|
|
1611
|
+
severityFilter: severityFilters,
|
|
1612
|
+
regionFilter,
|
|
1613
|
+
searchQuery,
|
|
1614
|
+
showLabels,
|
|
1615
|
+
scale,
|
|
1616
|
+
animated,
|
|
1617
|
+
onPointClick: () => {}
|
|
1618
|
+
}),
|
|
1619
|
+
/* @__PURE__ */ jsx(VitalPointMarkers3D, {
|
|
1620
|
+
position: player2Position3D,
|
|
1621
|
+
visible: overlayVisible,
|
|
1622
|
+
severityFilter: severityFilters,
|
|
1623
|
+
regionFilter,
|
|
1624
|
+
searchQuery,
|
|
1625
|
+
showLabels,
|
|
1626
|
+
scale,
|
|
1627
|
+
animated,
|
|
1628
|
+
onPointClick: () => {}
|
|
1629
|
+
}),
|
|
1630
|
+
/* @__PURE__ */ jsx(VitalPointOverlayControlsHtml, {
|
|
1631
|
+
screenPosition: {
|
|
1632
|
+
top: `${layoutConstants.hudHeight + layoutConstants.padding}px`,
|
|
1633
|
+
left: `${layoutConstants.padding}px`
|
|
1634
|
+
},
|
|
1635
|
+
visible: overlayVisible,
|
|
1636
|
+
onVisibleChange: setOverlayVisible,
|
|
1637
|
+
severityFilters,
|
|
1638
|
+
onSeverityFiltersChange: setSeverityFilters,
|
|
1639
|
+
regionFilter,
|
|
1640
|
+
onRegionFilterChange: setRegionFilter,
|
|
1641
|
+
searchQuery,
|
|
1642
|
+
onSearchQueryChange: setSearchQuery,
|
|
1643
|
+
showLabels,
|
|
1644
|
+
onShowLabelsChange: setShowLabels,
|
|
1645
|
+
animated,
|
|
1646
|
+
onAnimatedChange: setAnimated,
|
|
1647
|
+
scale,
|
|
1648
|
+
onScaleChange: setScale,
|
|
1649
|
+
isMobile
|
|
1650
|
+
})
|
|
1651
|
+
] }),
|
|
1652
|
+
/* @__PURE__ */ jsx(DamageNumbers, {
|
|
1653
|
+
damages: feedbackState.damageNumbers,
|
|
1654
|
+
isMobile,
|
|
1655
|
+
arenaBounds
|
|
1636
1656
|
}),
|
|
1637
|
-
/* @__PURE__ */ jsx(
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1657
|
+
/* @__PURE__ */ jsx(ActionFeedback, {
|
|
1658
|
+
feedbacks: feedbackState.actionFeedbacks,
|
|
1659
|
+
isMobile,
|
|
1660
|
+
arenaBounds
|
|
1661
|
+
}),
|
|
1662
|
+
/* @__PURE__ */ jsx(ComboCounter, {
|
|
1663
|
+
combo: feedbackState.comboCount,
|
|
1664
|
+
isMobile
|
|
1665
|
+
}),
|
|
1666
|
+
feedbackState.currentTechnique && /* @__PURE__ */ jsx(TechniqueName, {
|
|
1667
|
+
korean: feedbackState.currentTechnique.korean,
|
|
1668
|
+
english: feedbackState.currentTechnique.english,
|
|
1669
|
+
isMobile,
|
|
1670
|
+
onComplete: () => feedbackActions.hideTechnique()
|
|
1671
|
+
}),
|
|
1672
|
+
false,
|
|
1673
|
+
/* @__PURE__ */ jsx(StanceChangeIndicator, {
|
|
1674
|
+
currentStance: currentStanceIndex,
|
|
1675
|
+
previousStance,
|
|
1676
|
+
isMobile
|
|
1677
|
+
}),
|
|
1678
|
+
/* @__PURE__ */ jsx(KeyboardHints, {
|
|
1679
|
+
visible: showHints,
|
|
1680
|
+
currentStance: currentStanceIndex,
|
|
1681
|
+
isMobile
|
|
1682
|
+
}),
|
|
1683
|
+
/* @__PURE__ */ jsx(InputBufferDisplay, {
|
|
1684
|
+
queuedInputs,
|
|
1685
|
+
isMobile
|
|
1686
|
+
}),
|
|
1687
|
+
validPlayers[0] && /* @__PURE__ */ jsx(BalanceIndicatorOverlayHtml, {
|
|
1688
|
+
player: validPlayers[0],
|
|
1689
|
+
currentTime,
|
|
1690
|
+
position: [
|
|
1691
|
+
-2.5,
|
|
1692
|
+
2.5,
|
|
1693
|
+
-1
|
|
1694
|
+
],
|
|
1695
|
+
isMobile
|
|
1696
|
+
}),
|
|
1697
|
+
validPlayers[1] && /* @__PURE__ */ jsx(BalanceIndicatorOverlayHtml, {
|
|
1698
|
+
player: validPlayers[1],
|
|
1699
|
+
currentTime,
|
|
1700
|
+
position: [
|
|
1701
|
+
2.5,
|
|
1702
|
+
2.5,
|
|
1703
|
+
-1
|
|
1704
|
+
],
|
|
1656
1705
|
isMobile
|
|
1706
|
+
}),
|
|
1707
|
+
process.env.NODE_ENV === "development" && showPerformanceMonitor && /* @__PURE__ */ jsx(FPSMonitor, {
|
|
1708
|
+
enabled: true,
|
|
1709
|
+
warningThreshold: 50,
|
|
1710
|
+
criticalThreshold: 30
|
|
1657
1711
|
})
|
|
1658
|
-
]
|
|
1659
|
-
|
|
1660
|
-
damages: feedbackState.damageNumbers,
|
|
1661
|
-
isMobile,
|
|
1662
|
-
arenaBounds
|
|
1663
|
-
}),
|
|
1664
|
-
/* @__PURE__ */ jsx(ActionFeedback, {
|
|
1665
|
-
feedbacks: feedbackState.actionFeedbacks,
|
|
1666
|
-
isMobile,
|
|
1667
|
-
arenaBounds
|
|
1668
|
-
}),
|
|
1669
|
-
/* @__PURE__ */ jsx(ComboCounter, {
|
|
1670
|
-
combo: feedbackState.comboCount,
|
|
1671
|
-
isMobile
|
|
1672
|
-
}),
|
|
1673
|
-
feedbackState.currentTechnique && /* @__PURE__ */ jsx(TechniqueName, {
|
|
1674
|
-
korean: feedbackState.currentTechnique.korean,
|
|
1675
|
-
english: feedbackState.currentTechnique.english,
|
|
1676
|
-
isMobile,
|
|
1677
|
-
onComplete: () => feedbackActions.hideTechnique()
|
|
1678
|
-
}),
|
|
1679
|
-
false,
|
|
1680
|
-
/* @__PURE__ */ jsx(StanceChangeIndicator, {
|
|
1681
|
-
currentStance: currentStanceIndex,
|
|
1682
|
-
previousStance,
|
|
1683
|
-
isMobile
|
|
1684
|
-
}),
|
|
1685
|
-
/* @__PURE__ */ jsx(KeyboardHints, {
|
|
1686
|
-
visible: showHints,
|
|
1687
|
-
currentStance: currentStanceIndex,
|
|
1688
|
-
isMobile
|
|
1689
|
-
}),
|
|
1690
|
-
/* @__PURE__ */ jsx(InputBufferDisplay, {
|
|
1691
|
-
queuedInputs,
|
|
1692
|
-
isMobile
|
|
1693
|
-
}),
|
|
1694
|
-
validPlayers[0] && /* @__PURE__ */ jsx(BalanceIndicatorOverlayHtml, {
|
|
1695
|
-
player: validPlayers[0],
|
|
1696
|
-
currentTime,
|
|
1697
|
-
position: [
|
|
1698
|
-
-2.5,
|
|
1699
|
-
2.5,
|
|
1700
|
-
-1
|
|
1701
|
-
],
|
|
1702
|
-
isMobile
|
|
1703
|
-
}),
|
|
1704
|
-
validPlayers[1] && /* @__PURE__ */ jsx(BalanceIndicatorOverlayHtml, {
|
|
1705
|
-
player: validPlayers[1],
|
|
1706
|
-
currentTime,
|
|
1707
|
-
position: [
|
|
1708
|
-
2.5,
|
|
1709
|
-
2.5,
|
|
1710
|
-
-1
|
|
1711
|
-
],
|
|
1712
|
-
isMobile
|
|
1713
|
-
}),
|
|
1714
|
-
process.env.NODE_ENV === "development" && showPerformanceMonitor && /* @__PURE__ */ jsx(FPSMonitor, {
|
|
1715
|
-
enabled: true,
|
|
1716
|
-
warningThreshold: 50,
|
|
1717
|
-
criticalThreshold: 30
|
|
1718
|
-
})
|
|
1719
|
-
] }),
|
|
1712
|
+
]
|
|
1713
|
+
}),
|
|
1720
1714
|
isMobile ? /* @__PURE__ */ jsxs(EffectComposer, {
|
|
1721
1715
|
multisampling: 0,
|
|
1722
1716
|
children: [
|