blacktrigram 0.7.8 โ 0.7.9
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/ARCHITECTURE.md +2404 -0
- package/COMBAT_ARCHITECTURE.md +3322 -0
- package/CONTROLS.md +639 -0
- package/CRA-ASSESSMENT.md +508 -0
- package/DATA_MODEL.md +675 -0
- package/ISMS_REFERENCE_MAPPING.md +513 -0
- package/SECURITY_ARCHITECTURE.md +1160 -0
- package/THREAT_MODEL.md +1163 -0
- package/lib/components/screens/intro/IntroScreen3D.js +1 -1
- package/lib/components/shared/ui/SplashScreen.js +2 -2
- package/lib/data/archetypeClothing.js +1 -1
- package/lib/data/archetypePhysicalAttributes.js +158 -1
- package/lib/data/archetypePhysicalAttributes.js.map +1 -1
- package/lib/data/index.d.ts +14 -0
- package/lib/data/index.d.ts.map +1 -0
- package/lib/data/index.js +43 -0
- package/lib/data/index.js.map +1 -0
- package/lib/data/techniqueMappings.js +47 -2
- package/lib/data/techniqueMappings.js.map +1 -1
- package/lib/data/techniques.js +1 -1
- package/lib/hooks/index.d.ts +29 -0
- package/lib/hooks/index.d.ts.map +1 -0
- package/lib/hooks/index.js +53 -0
- package/lib/hooks/index.js.map +1 -0
- package/lib/hooks/useDebounce.js +52 -0
- package/lib/hooks/useDebounce.js.map +1 -0
- package/lib/hooks/usePauseMenu.js +60 -0
- package/lib/hooks/usePauseMenu.js.map +1 -0
- package/lib/hooks/useResponsiveLayout.js +160 -0
- package/lib/hooks/useResponsiveLayout.js.map +1 -0
- package/lib/hooks/useWebGLContextLossHandler.js +36 -1
- package/lib/hooks/useWebGLContextLossHandler.js.map +1 -1
- package/lib/hooks/useWindowSize.js +19 -1
- package/lib/hooks/useWindowSize.js.map +1 -1
- package/lib/index.d.ts +2 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +3 -1
- package/package.json +19 -3
package/DATA_MODEL.md
ADDED
|
@@ -0,0 +1,675 @@
|
|
|
1
|
+
# ๐ Black Trigram (ํ๊ด) Data Model
|
|
2
|
+
|
|
3
|
+
## ๐ Related Documentation
|
|
4
|
+
|
|
5
|
+
| Document | Focus | Description |
|
|
6
|
+
| --------------------------------------------- | ---------------- | ---------------------------------------------- |
|
|
7
|
+
| [Architecture](ARCHITECTURE.md) | ๐๏ธ Structure | C4 model showing system components |
|
|
8
|
+
| [Flowchart](FLOWCHART.md) | ๐ Process Flow | Game flow and state transitions |
|
|
9
|
+
| [State Diagram](STATEDIAGRAM.md) | ๐ฎ State Machine | Combat and game state management |
|
|
10
|
+
| [Combat Architecture](COMBAT_ARCHITECTURE.md) | โ๏ธ Combat System | Detailed combat mechanics implementation |
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## ๐ฏ Overview
|
|
15
|
+
|
|
16
|
+
Black Trigram (ํ๊ด) is a frontend-only Korean martial arts combat simulator with a comprehensive data model supporting authentic vital point targeting, eight trigram stances, and realistic combat physics. All data structures are implemented in TypeScript with strict type safety and readonly properties for immutability.
|
|
17
|
+
|
|
18
|
+
### **Data Architecture Principles**
|
|
19
|
+
|
|
20
|
+
- โ
**Type Safety**: Strict TypeScript with no implicit any
|
|
21
|
+
- โ
**Immutability**: Readonly properties throughout.
|
|
22
|
+
- โ
**Korean Cultural Authenticity**: Bilingual Korean-English text support
|
|
23
|
+
- โ
**Session-Only Storage**: No backend persistence (browser session state)
|
|
24
|
+
- โ
**Functional Design**: Pure functions and immutable state updates
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## ๐ Core Type System
|
|
29
|
+
|
|
30
|
+
### **Entity Relationship Diagram**
|
|
31
|
+
|
|
32
|
+
```mermaid
|
|
33
|
+
erDiagram
|
|
34
|
+
PLAYER ||--|| PLAYER_ARCHETYPE : "has"
|
|
35
|
+
PLAYER ||--o{ STATUS_EFFECT : "suffers"
|
|
36
|
+
PLAYER ||--|| TRIGRAM_STANCE : "assumes"
|
|
37
|
+
PLAYER ||--o{ VITAL_POINT_STATE : "tracks"
|
|
38
|
+
PLAYER ||--|| COMBAT_STATE : "in"
|
|
39
|
+
|
|
40
|
+
COMBAT_SYSTEM ||--|| PLAYER : "manages_player1"
|
|
41
|
+
COMBAT_SYSTEM ||--|| PLAYER : "manages_player2"
|
|
42
|
+
COMBAT_SYSTEM ||--o{ HIT_EFFECT : "generates"
|
|
43
|
+
COMBAT_SYSTEM ||--o{ ENVIRONMENTAL_EFFECT : "produces"
|
|
44
|
+
|
|
45
|
+
TRIGRAM_STANCE ||--o{ TECHNIQUE : "enables"
|
|
46
|
+
VITAL_POINT ||--|| VITAL_POINT_CATEGORY : "belongs_to"
|
|
47
|
+
VITAL_POINT ||--|| VITAL_POINT_SEVERITY : "has_severity"
|
|
48
|
+
VITAL_POINT ||--o{ VITAL_POINT_EFFECT : "causes"
|
|
49
|
+
|
|
50
|
+
PLAYER {
|
|
51
|
+
string id PK
|
|
52
|
+
KoreanText name
|
|
53
|
+
PlayerArchetype archetype
|
|
54
|
+
number health
|
|
55
|
+
number ki
|
|
56
|
+
number stamina
|
|
57
|
+
TrigramStance currentStance
|
|
58
|
+
Position position
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
PLAYER_ARCHETYPE {
|
|
62
|
+
string id PK
|
|
63
|
+
KoreanText name
|
|
64
|
+
number baseHealth
|
|
65
|
+
number baseKi
|
|
66
|
+
TrigramStance coreStance
|
|
67
|
+
number attackPower
|
|
68
|
+
number defense
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
TRIGRAM_STANCE {
|
|
72
|
+
string id PK
|
|
73
|
+
KoreanText name
|
|
74
|
+
string element
|
|
75
|
+
string symbol
|
|
76
|
+
number energyCost
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
VITAL_POINT {
|
|
80
|
+
string id PK
|
|
81
|
+
KoreanText name
|
|
82
|
+
BodyRegion location
|
|
83
|
+
VitalPointCategory category
|
|
84
|
+
VitalPointSeverity severity
|
|
85
|
+
number damageMultiplier
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
STATUS_EFFECT {
|
|
89
|
+
string id PK
|
|
90
|
+
string type
|
|
91
|
+
number duration
|
|
92
|
+
number intensity
|
|
93
|
+
number startTime
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
HIT_EFFECT {
|
|
97
|
+
string id PK
|
|
98
|
+
HitEffectType type
|
|
99
|
+
Position position
|
|
100
|
+
number timestamp
|
|
101
|
+
number duration
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## ๐ TypeScript Interface Examples
|
|
108
|
+
|
|
109
|
+
The following are representative TypeScript interfaces from the codebase, implementing the data model described above. All interfaces use strict typing and readonly properties for immutability.
|
|
110
|
+
|
|
111
|
+
### **Core Interfaces from src/types/common.ts**
|
|
112
|
+
|
|
113
|
+
#### `KoreanText` - Bilingual Text Support
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
// src/types/common.ts
|
|
117
|
+
export interface KoreanText {
|
|
118
|
+
readonly korean: string; // ํ๊ธ ํ
์คํธ
|
|
119
|
+
readonly english: string; // English translation
|
|
120
|
+
readonly romanized?: string; // Optional romanization (e.g., "Geup-so-gyeok")
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
#### `Position` - 2D Spatial Coordinates
|
|
125
|
+
|
|
126
|
+
```typescript
|
|
127
|
+
// src/types/common.ts
|
|
128
|
+
export interface Position {
|
|
129
|
+
readonly x: number;
|
|
130
|
+
readonly y: number;
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
**Note**: The `Position` type represents 2D coordinates. For 3D rendering with Three.js, the combat system maps 2D positions to 3D space:
|
|
135
|
+
- `x` (horizontal) โ Three.js `x` axis
|
|
136
|
+
- `y` (depth) โ Three.js `z` axis
|
|
137
|
+
- Three.js `y` axis represents height/elevation (handled separately in rendering layer)
|
|
138
|
+
|
|
139
|
+
#### Enum Types - Game Constants
|
|
140
|
+
|
|
141
|
+
```typescript
|
|
142
|
+
// src/types/common.ts
|
|
143
|
+
export enum PlayerArchetype {
|
|
144
|
+
MUSA = "musa", // ๋ฌด์ฌ - Traditional Warrior
|
|
145
|
+
AMSALJA = "amsalja", // ์์ด์ - Shadow Assassin
|
|
146
|
+
HACKER = "hacker", // ํด์ปค - Cyber Warrior
|
|
147
|
+
JEONGBO_YOWON = "jeongbo_yowon", // ์ ๋ณด์์ - Intelligence Operative
|
|
148
|
+
JOJIK_POKRYEOKBAE = "jojik_pokryeokbae", // ์กฐ์งํญ๋ ฅ๋ฐฐ - Organized Crime
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export enum TrigramStance {
|
|
152
|
+
GEON = "geon", // โฐ ๊ฑด - Heaven
|
|
153
|
+
TAE = "tae", // โฑ ํ - Lake
|
|
154
|
+
LI = "li", // โฒ ๋ฆฌ - Fire
|
|
155
|
+
JIN = "jin", // โณ ์ง - Thunder
|
|
156
|
+
SON = "son", // โด ์ - Wind
|
|
157
|
+
GAM = "gam", // โต ๊ฐ - Water
|
|
158
|
+
GAN = "gan", // โถ ๊ฐ - Mountain
|
|
159
|
+
GON = "gon", // โท ๊ณค - Earth
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export enum CombatState {
|
|
163
|
+
IDLE = "idle",
|
|
164
|
+
ATTACKING = "attacking",
|
|
165
|
+
DEFENDING = "defending",
|
|
166
|
+
STUNNED = "stunned",
|
|
167
|
+
RECOVERING = "recovering",
|
|
168
|
+
COUNTERING = "countering",
|
|
169
|
+
TRANSITIONING = "transitioning",
|
|
170
|
+
}
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### **Player System from src/systems/player.ts**
|
|
174
|
+
|
|
175
|
+
#### `PlayerState` - Complete Player State
|
|
176
|
+
|
|
177
|
+
```typescript
|
|
178
|
+
// src/systems/player.ts
|
|
179
|
+
export interface PlayerState {
|
|
180
|
+
// Identity
|
|
181
|
+
readonly id: string;
|
|
182
|
+
readonly name: KoreanText;
|
|
183
|
+
readonly archetype: PlayerArchetype;
|
|
184
|
+
|
|
185
|
+
// Core Resources
|
|
186
|
+
readonly health: number;
|
|
187
|
+
readonly maxHealth: number;
|
|
188
|
+
readonly ki: number; // ๊ธฐ - Internal energy
|
|
189
|
+
readonly maxKi: number;
|
|
190
|
+
readonly stamina: number;
|
|
191
|
+
readonly maxStamina: number;
|
|
192
|
+
readonly energy: number;
|
|
193
|
+
readonly maxEnergy: number;
|
|
194
|
+
|
|
195
|
+
// Combat Attributes
|
|
196
|
+
readonly attackPower: number;
|
|
197
|
+
readonly defense: number;
|
|
198
|
+
readonly speed: number;
|
|
199
|
+
readonly technique: number;
|
|
200
|
+
readonly pain: number; // Pain tolerance (0-100)
|
|
201
|
+
readonly consciousness: number; // Awareness level (0-100)
|
|
202
|
+
readonly balance: number; // Physical stability (0-100)
|
|
203
|
+
readonly momentum: number; // Combat momentum (-100 to 100)
|
|
204
|
+
|
|
205
|
+
// Combat State
|
|
206
|
+
readonly currentStance: TrigramStance;
|
|
207
|
+
readonly combatState: CombatState;
|
|
208
|
+
readonly position: Position;
|
|
209
|
+
readonly isBlocking: boolean;
|
|
210
|
+
readonly isStunned: boolean;
|
|
211
|
+
readonly isCountering: boolean;
|
|
212
|
+
readonly lastActionTime: number;
|
|
213
|
+
readonly recoveryTime: number;
|
|
214
|
+
readonly lastStanceChangeTime: number;
|
|
215
|
+
|
|
216
|
+
// Status Effects
|
|
217
|
+
readonly statusEffects: readonly StatusEffect[];
|
|
218
|
+
readonly activeEffects: readonly string[];
|
|
219
|
+
|
|
220
|
+
// Vital Points State
|
|
221
|
+
readonly vitalPoints: readonly {
|
|
222
|
+
readonly id: string;
|
|
223
|
+
readonly isHit: boolean;
|
|
224
|
+
readonly damage: number;
|
|
225
|
+
readonly lastHitTime: number;
|
|
226
|
+
}[];
|
|
227
|
+
|
|
228
|
+
// Match Statistics
|
|
229
|
+
readonly totalDamageReceived: number;
|
|
230
|
+
readonly totalDamageDealt: number;
|
|
231
|
+
readonly hitsTaken: number;
|
|
232
|
+
readonly hitsLanded: number;
|
|
233
|
+
readonly perfectStrikes: number;
|
|
234
|
+
readonly vitalPointHits: number;
|
|
235
|
+
}
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
### **Combat System from src/systems/types.ts**
|
|
239
|
+
|
|
240
|
+
#### `StatusEffect` - Status Effects and Debuffs
|
|
241
|
+
|
|
242
|
+
```typescript
|
|
243
|
+
// src/systems/types.ts
|
|
244
|
+
export interface StatusEffect {
|
|
245
|
+
readonly id: string;
|
|
246
|
+
readonly type: string;
|
|
247
|
+
readonly intensity: EffectIntensity;
|
|
248
|
+
readonly duration: number; // Duration in milliseconds
|
|
249
|
+
readonly description: KoreanText;
|
|
250
|
+
readonly stackable: boolean;
|
|
251
|
+
readonly source: string; // What caused this effect
|
|
252
|
+
readonly startTime: number;
|
|
253
|
+
readonly endTime: number;
|
|
254
|
+
}
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
#### `HitEffect` - Visual Combat Feedback
|
|
258
|
+
|
|
259
|
+
```typescript
|
|
260
|
+
// src/systems/types.ts
|
|
261
|
+
export interface HitEffect {
|
|
262
|
+
readonly id: string;
|
|
263
|
+
readonly type: HitEffectType;
|
|
264
|
+
readonly attackerId: string;
|
|
265
|
+
readonly defenderId: string;
|
|
266
|
+
readonly timestamp: number;
|
|
267
|
+
readonly duration: number;
|
|
268
|
+
readonly position?: Position;
|
|
269
|
+
readonly velocity?: { x: number; y: number };
|
|
270
|
+
readonly color?: number;
|
|
271
|
+
readonly size?: number;
|
|
272
|
+
readonly alpha?: number;
|
|
273
|
+
readonly damageAmount?: number;
|
|
274
|
+
readonly vitalPointId?: string;
|
|
275
|
+
readonly intensity: number;
|
|
276
|
+
}
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
#### `PlayerArchetypeData` - Archetype Configuration
|
|
280
|
+
|
|
281
|
+
```typescript
|
|
282
|
+
// src/systems/types.ts
|
|
283
|
+
export interface PlayerArchetypeData {
|
|
284
|
+
readonly id: string;
|
|
285
|
+
readonly name: KoreanText;
|
|
286
|
+
readonly description: KoreanText;
|
|
287
|
+
readonly baseHealth: number;
|
|
288
|
+
readonly baseKi: number;
|
|
289
|
+
readonly baseStamina: number;
|
|
290
|
+
readonly coreStance: TrigramStance;
|
|
291
|
+
readonly theme: {
|
|
292
|
+
primary: number; // Primary color (hex)
|
|
293
|
+
secondary: number; // Secondary color (hex)
|
|
294
|
+
};
|
|
295
|
+
readonly stats: {
|
|
296
|
+
attackPower: number;
|
|
297
|
+
defense: number;
|
|
298
|
+
speed: number;
|
|
299
|
+
technique: number;
|
|
300
|
+
};
|
|
301
|
+
readonly favoredStances: readonly TrigramStance[];
|
|
302
|
+
readonly specialAbilities: readonly string[];
|
|
303
|
+
readonly philosophy: KoreanText;
|
|
304
|
+
}
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
### **Type Safety and Immutability Patterns**
|
|
308
|
+
|
|
309
|
+
All interfaces in Black Trigram follow these principles:
|
|
310
|
+
|
|
311
|
+
1. **Readonly Properties**: All object properties are marked `readonly` to prevent accidental mutation
|
|
312
|
+
2. **Strict Typing**: No `any` types; explicit types throughout
|
|
313
|
+
3. **Immutable Arrays**: Arrays use `readonly` modifier for immutability
|
|
314
|
+
4. **Functional Updates**: State changes create new objects rather than mutating existing ones
|
|
315
|
+
|
|
316
|
+
Example of immutable state update:
|
|
317
|
+
|
|
318
|
+
```typescript
|
|
319
|
+
// Immutable player health update
|
|
320
|
+
function updatePlayerHealth(
|
|
321
|
+
player: PlayerState,
|
|
322
|
+
healthChange: number
|
|
323
|
+
): PlayerState {
|
|
324
|
+
return {
|
|
325
|
+
...player,
|
|
326
|
+
health: Math.max(0, Math.min(player.maxHealth, player.health + healthChange)),
|
|
327
|
+
totalDamageReceived: healthChange < 0
|
|
328
|
+
? player.totalDamageReceived + Math.abs(healthChange)
|
|
329
|
+
: player.totalDamageReceived,
|
|
330
|
+
};
|
|
331
|
+
}
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
---
|
|
335
|
+
|
|
336
|
+
## ๐ฆด Skeletal Animation Data Model
|
|
337
|
+
|
|
338
|
+
### **28-Bone Skeletal Hierarchy**
|
|
339
|
+
|
|
340
|
+
Black Trigram implements a performance-optimized skeletal animation system with 28 core bones, expandable to 66 bones with full hand detail for close-up views.
|
|
341
|
+
|
|
342
|
+
#### **Core Bone Structure (28 bones)**
|
|
343
|
+
|
|
344
|
+
```mermaid
|
|
345
|
+
graph TD
|
|
346
|
+
PELVIS[PELVIS - Root]
|
|
347
|
+
|
|
348
|
+
PELVIS --> SPINE_LOWER[SPINE_LOWER]
|
|
349
|
+
SPINE_LOWER --> SPINE_MIDDLE[SPINE_MIDDLE]
|
|
350
|
+
SPINE_MIDDLE --> SPINE_UPPER[SPINE_UPPER]
|
|
351
|
+
|
|
352
|
+
SPINE_UPPER --> NECK[NECK]
|
|
353
|
+
NECK --> HEAD[HEAD]
|
|
354
|
+
|
|
355
|
+
SPINE_UPPER --> SHOULDER_L[SHOULDER_L]
|
|
356
|
+
SHOULDER_L --> UPPER_ARM_L[UPPER_ARM_L]
|
|
357
|
+
UPPER_ARM_L --> ELBOW_L[ELBOW_L]
|
|
358
|
+
ELBOW_L --> FOREARM_L[FOREARM_L]
|
|
359
|
+
FOREARM_L --> WRIST_L[WRIST_L]
|
|
360
|
+
WRIST_L --> HAND_L[HAND_L]
|
|
361
|
+
|
|
362
|
+
SPINE_UPPER --> SHOULDER_R[SHOULDER_R]
|
|
363
|
+
SHOULDER_R --> UPPER_ARM_R[UPPER_ARM_R]
|
|
364
|
+
UPPER_ARM_R --> ELBOW_R[ELBOW_R]
|
|
365
|
+
ELBOW_R --> FOREARM_R[FOREARM_R]
|
|
366
|
+
FOREARM_R --> WRIST_R[WRIST_R]
|
|
367
|
+
WRIST_R --> HAND_R[HAND_R]
|
|
368
|
+
|
|
369
|
+
PELVIS --> HIP_L[HIP_L]
|
|
370
|
+
HIP_L --> THIGH_L[THIGH_L]
|
|
371
|
+
THIGH_L --> KNEE_L[KNEE_L]
|
|
372
|
+
KNEE_L --> SHIN_L[SHIN_L]
|
|
373
|
+
SHIN_L --> FOOT_L[FOOT_L]
|
|
374
|
+
|
|
375
|
+
PELVIS --> HIP_R[HIP_R]
|
|
376
|
+
HIP_R --> THIGH_R[THIGH_R]
|
|
377
|
+
THIGH_R --> KNEE_R[KNEE_R]
|
|
378
|
+
KNEE_R --> SHIN_R[SHIN_R]
|
|
379
|
+
SHIN_R --> FOOT_R[FOOT_R]
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
#### **Skeletal Rig TypeScript Interface**
|
|
383
|
+
|
|
384
|
+
```typescript
|
|
385
|
+
// src/types/skeletal.ts
|
|
386
|
+
export interface Bone {
|
|
387
|
+
readonly name: string;
|
|
388
|
+
parent: Bone | null;
|
|
389
|
+
position: THREE.Vector3;
|
|
390
|
+
rotation: THREE.Euler;
|
|
391
|
+
scale: THREE.Vector3;
|
|
392
|
+
children: Bone[];
|
|
393
|
+
readonly length: number;
|
|
394
|
+
readonly restPosition: THREE.Vector3;
|
|
395
|
+
readonly restRotation: THREE.Euler;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
export interface SkeletalRig {
|
|
399
|
+
readonly root: Bone;
|
|
400
|
+
readonly bones: Map<string, Bone>;
|
|
401
|
+
readonly boneCount: number;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
export enum BoneName {
|
|
405
|
+
// Core (1)
|
|
406
|
+
PELVIS = "pelvis",
|
|
407
|
+
|
|
408
|
+
// Spine (3)
|
|
409
|
+
SPINE_LOWER = "spine_lower",
|
|
410
|
+
SPINE_MIDDLE = "spine_middle",
|
|
411
|
+
SPINE_UPPER = "spine_upper",
|
|
412
|
+
|
|
413
|
+
// Head (2)
|
|
414
|
+
NECK = "neck",
|
|
415
|
+
HEAD = "head",
|
|
416
|
+
|
|
417
|
+
// Left Arm (6)
|
|
418
|
+
SHOULDER_L = "shoulder_L",
|
|
419
|
+
UPPER_ARM_L = "upper_arm_L",
|
|
420
|
+
ELBOW_L = "elbow_L",
|
|
421
|
+
FOREARM_L = "forearm_L",
|
|
422
|
+
WRIST_L = "wrist_L",
|
|
423
|
+
HAND_L = "hand_L",
|
|
424
|
+
|
|
425
|
+
// Right Arm (6)
|
|
426
|
+
SHOULDER_R = "shoulder_R",
|
|
427
|
+
UPPER_ARM_R = "upper_arm_R",
|
|
428
|
+
ELBOW_R = "elbow_R",
|
|
429
|
+
FOREARM_R = "forearm_R",
|
|
430
|
+
WRIST_R = "wrist_R",
|
|
431
|
+
HAND_R = "hand_R",
|
|
432
|
+
|
|
433
|
+
// Left Leg (5)
|
|
434
|
+
HIP_L = "hip_L",
|
|
435
|
+
THIGH_L = "thigh_L",
|
|
436
|
+
KNEE_L = "knee_L",
|
|
437
|
+
SHIN_L = "shin_L",
|
|
438
|
+
FOOT_L = "foot_L",
|
|
439
|
+
|
|
440
|
+
// Right Leg (5)
|
|
441
|
+
HIP_R = "hip_R",
|
|
442
|
+
THIGH_R = "thigh_R",
|
|
443
|
+
KNEE_R = "knee_R",
|
|
444
|
+
SHIN_R = "shin_R",
|
|
445
|
+
FOOT_R = "foot_R",
|
|
446
|
+
}
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
---
|
|
450
|
+
|
|
451
|
+
## ๐ Hand Animation System (7 Hand Poses)
|
|
452
|
+
|
|
453
|
+
### **Korean Martial Arts Hand Poses**
|
|
454
|
+
|
|
455
|
+
```typescript
|
|
456
|
+
// src/types/hand-animation.ts
|
|
457
|
+
export enum HandPoseType {
|
|
458
|
+
FIST = "fist", // ์ฃผ๋จน - Closed fist for punching
|
|
459
|
+
KNIFE_HAND = "knife_hand", // ์๋ - Knife-hand strike
|
|
460
|
+
SPEAR_HAND = "spear_hand", // ๊ด์ - Spear-hand thrust
|
|
461
|
+
PALM_HEEL = "palm_heel", // ์ฅ๋ ฅ - Palm-heel strike
|
|
462
|
+
GRAPPLING = "grappling", // ์ก๊ธฐ - Grappling hand
|
|
463
|
+
OPEN = "open", // ํด๊ธฐ - Open hand neutral
|
|
464
|
+
RELAXED = "relaxed", // ํด์ - Relaxed natural
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
export interface HandPose {
|
|
468
|
+
readonly type: HandPoseType;
|
|
469
|
+
readonly nameKorean: string;
|
|
470
|
+
readonly nameEnglish: string;
|
|
471
|
+
readonly romanized: string;
|
|
472
|
+
readonly fingerCurl: FingerCurl;
|
|
473
|
+
readonly fingerSpread: FingerSpread;
|
|
474
|
+
readonly wristRotation: THREE.Euler;
|
|
475
|
+
readonly description: {
|
|
476
|
+
readonly korean: string;
|
|
477
|
+
readonly english: string;
|
|
478
|
+
};
|
|
479
|
+
readonly martialArtOrigin: "taekwondo" | "hapkido" | "taekyon" | "traditional";
|
|
480
|
+
readonly strikingSurface: "knuckles" | "palm_heel" | "knife_edge" | "fingertips" | "whole_hand";
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
export interface FingerCurl {
|
|
484
|
+
readonly thumb: number; // 0 = extended, 1 = curled
|
|
485
|
+
readonly index: number;
|
|
486
|
+
readonly middle: number;
|
|
487
|
+
readonly ring: number;
|
|
488
|
+
readonly pinky: number;
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
export interface FingerSpread {
|
|
492
|
+
readonly thumbIndex: number; // 0 = together, 1 = spread
|
|
493
|
+
readonly indexMiddle: number;
|
|
494
|
+
readonly middleRing: number;
|
|
495
|
+
readonly ringPinky: number;
|
|
496
|
+
}
|
|
497
|
+
```
|
|
498
|
+
|
|
499
|
+
---
|
|
500
|
+
|
|
501
|
+
## ๐ฏ Vital Point System (70 Points)
|
|
502
|
+
|
|
503
|
+
### **Complete Vital Points Database**
|
|
504
|
+
|
|
505
|
+
Black Trigram implements 70 authentic Korean martial arts vital points (๊ธ์) based on traditional anatomical targeting knowledge.
|
|
506
|
+
|
|
507
|
+
#### **Vital Point Distribution**
|
|
508
|
+
|
|
509
|
+
- **Head**: 12 points (temple, jaw, nose, eye, ear, throat, back of head)
|
|
510
|
+
- **Torso**: 24 points (heart, solar plexus, liver, spleen, kidneys, floating ribs)
|
|
511
|
+
- **Arms**: 17 points (shoulders, elbows, wrists, nerve clusters)
|
|
512
|
+
- **Legs**: 17 points (hips, knees, shins, ankles, pressure points)
|
|
513
|
+
|
|
514
|
+
#### **Vital Point TypeScript Interface**
|
|
515
|
+
|
|
516
|
+
```typescript
|
|
517
|
+
// src/systems/vitalpoint/types.ts
|
|
518
|
+
export interface VitalPoint {
|
|
519
|
+
readonly id: string;
|
|
520
|
+
readonly names: {
|
|
521
|
+
readonly korean: string;
|
|
522
|
+
readonly english: string;
|
|
523
|
+
readonly romanized: string;
|
|
524
|
+
};
|
|
525
|
+
readonly position: Position;
|
|
526
|
+
readonly category: VitalPointCategory;
|
|
527
|
+
readonly severity: VitalPointSeverity;
|
|
528
|
+
readonly baseDamage?: number;
|
|
529
|
+
readonly effects: readonly VitalPointEffect[];
|
|
530
|
+
readonly description: KoreanText;
|
|
531
|
+
readonly targetingDifficulty: number; // 0.0-1.0
|
|
532
|
+
readonly effectiveStances: readonly TrigramStance[];
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
export enum VitalPointCategory {
|
|
536
|
+
NEUROLOGICAL = "neurological", // ์ ๊ฒฝ๊ณ - Nerve strikes
|
|
537
|
+
SKELETAL = "skeletal", // ๊ณจ๊ฒฉ๊ณ - Bone targets
|
|
538
|
+
VASCULAR = "vascular", // ํ๊ด๊ณ - Blood vessels
|
|
539
|
+
MUSCULAR = "muscular", // ๊ทผ์ก๊ณ - Muscle groups
|
|
540
|
+
RESPIRATORY = "respiratory", // ํธํก๊ณ - Breathing targets
|
|
541
|
+
INTERNAL = "internal", // ๋ด๋ถ - Internal organs
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
export enum VitalPointSeverity {
|
|
545
|
+
CRITICAL = "critical", // ์น๋ช
์ - Lethal potential
|
|
546
|
+
MAJOR = "major", // ์ค๋ - Severe injury
|
|
547
|
+
MODERATE = "moderate", // ๋ณดํต - Significant pain
|
|
548
|
+
MINOR = "minor", // ๊ฒฝ๋ฏธ - Minor disruption
|
|
549
|
+
}
|
|
550
|
+
```
|
|
551
|
+
|
|
552
|
+
---
|
|
553
|
+
|
|
554
|
+
## โ๏ธ Combat State Machine
|
|
555
|
+
|
|
556
|
+
### **Combat State Transitions**
|
|
557
|
+
|
|
558
|
+
```mermaid
|
|
559
|
+
stateDiagram-v2
|
|
560
|
+
[*] --> IDLE
|
|
561
|
+
|
|
562
|
+
IDLE --> ATTACKING: Execute Technique
|
|
563
|
+
IDLE --> DEFENDING: Block/Evade Input
|
|
564
|
+
IDLE --> TRANSITIONING: Change Stance
|
|
565
|
+
|
|
566
|
+
ATTACKING --> RECOVERING: Attack Completes
|
|
567
|
+
ATTACKING --> STUNNED: Hit During Attack
|
|
568
|
+
ATTACKING --> COUNTERING: Counter Window Hit
|
|
569
|
+
|
|
570
|
+
DEFENDING --> IDLE: Defense Ends
|
|
571
|
+
DEFENDING --> STUNNED: Guard Break
|
|
572
|
+
DEFENDING --> COUNTERING: Perfect Block
|
|
573
|
+
|
|
574
|
+
RECOVERING --> IDLE: Recovery Complete
|
|
575
|
+
RECOVERING --> STUNNED: Hit During Recovery
|
|
576
|
+
|
|
577
|
+
STUNNED --> RECOVERING: Stun Duration Ends
|
|
578
|
+
STUNNED --> [*]: Health Depleted
|
|
579
|
+
|
|
580
|
+
COUNTERING --> ATTACKING: Counter Attack
|
|
581
|
+
COUNTERING --> IDLE: Counter Window Expires
|
|
582
|
+
|
|
583
|
+
TRANSITIONING --> IDLE: Stance Change Complete
|
|
584
|
+
TRANSITIONING --> STUNNED: Hit During Transition
|
|
585
|
+
```
|
|
586
|
+
|
|
587
|
+
### **Combat State TypeScript Definitions**
|
|
588
|
+
|
|
589
|
+
```typescript
|
|
590
|
+
// src/types/common.ts
|
|
591
|
+
export enum CombatState {
|
|
592
|
+
IDLE = "idle", // ๋๊ธฐ - Ready stance
|
|
593
|
+
ATTACKING = "attacking", // ๊ณต๊ฒฉ - Executing technique
|
|
594
|
+
DEFENDING = "defending", // ๋ฐฉ์ด - Blocking/evading
|
|
595
|
+
STUNNED = "stunned", // ๊ธฐ์ - Unable to act
|
|
596
|
+
RECOVERING = "recovering", // ํ๋ณต - Post-attack recovery
|
|
597
|
+
COUNTERING = "countering", // ๋ฐ๊ฒฉ - Counter window active
|
|
598
|
+
TRANSITIONING = "transitioning", // ์ ํ - Changing stance
|
|
599
|
+
}
|
|
600
|
+
```
|
|
601
|
+
|
|
602
|
+
---
|
|
603
|
+
|
|
604
|
+
## ๐ Korean Text and Localization
|
|
605
|
+
|
|
606
|
+
### **Bilingual Text System**
|
|
607
|
+
|
|
608
|
+
```typescript
|
|
609
|
+
// src/types/common.ts
|
|
610
|
+
export interface KoreanText {
|
|
611
|
+
readonly korean: string; // ํ๊ธ ํ
์คํธ
|
|
612
|
+
readonly english: string; // English translation
|
|
613
|
+
readonly romanized?: string; // Optional romanization (e.g., "geup-so-gyeok")
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
// Usage example
|
|
617
|
+
const vitalPointName: KoreanText = {
|
|
618
|
+
korean: "ํ์ํ",
|
|
619
|
+
english: "Temple",
|
|
620
|
+
romanized: "taeyang-hyeol",
|
|
621
|
+
};
|
|
622
|
+
```
|
|
623
|
+
|
|
624
|
+
### **Text Encoding Standards**
|
|
625
|
+
|
|
626
|
+
- **Korean Text**: UTF-8 encoding (ํ๊ธ)
|
|
627
|
+
- **Romanization**: Revised Romanization of Korean (RR)
|
|
628
|
+
- **Font Support**: Noto Sans CJK for Korean characters
|
|
629
|
+
- **Accessibility**: Korean screen reader support with proper ARIA labels
|
|
630
|
+
|
|
631
|
+
---
|
|
632
|
+
|
|
633
|
+
## ๐ Data Security Considerations
|
|
634
|
+
|
|
635
|
+
### **Session-Only Storage Security**
|
|
636
|
+
|
|
637
|
+
- **No Backend Persistence**: All game state stored in browser session (sessionStorage/memory)
|
|
638
|
+
- **No PII Collection**: No personally identifiable information collected or stored
|
|
639
|
+
- **Client-Side Only**: No data transmitted to external servers
|
|
640
|
+
- **Memory Clearing**: Game state cleared on browser close
|
|
641
|
+
- **No Cookies**: Authentication not required for core gameplay
|
|
642
|
+
|
|
643
|
+
### **Future Cloud Persistence Security**
|
|
644
|
+
|
|
645
|
+
When backend persistence is implemented (see [FUTURE_DATA_MODEL.md](FUTURE_DATA_MODEL.md)), security controls will include:
|
|
646
|
+
|
|
647
|
+
- **Encryption at Rest**: DynamoDB encryption with AWS KMS
|
|
648
|
+
- **Encryption in Transit**: TLS 1.3 for all API communications
|
|
649
|
+
- **Access Control**: AWS IAM policies with least privilege
|
|
650
|
+
- **Audit Logging**: CloudTrail logging of all data access
|
|
651
|
+
- **Data Classification**: Per Hack23 ISMS Classification Framework
|
|
652
|
+
- **GDPR Compliance**: Right to erasure, data portability, consent management
|
|
653
|
+
|
|
654
|
+
### **ISMS Framework Alignment**
|
|
655
|
+
|
|
656
|
+
This data model aligns with:
|
|
657
|
+
- **[Secure Development Policy](https://github.com/Hack23/ISMS-PUBLIC/blob/main/Secure_Development_Policy.md)**: Immutable data structures, type safety
|
|
658
|
+
- **[Data Classification](https://github.com/Hack23/ISMS-PUBLIC/blob/main/CLASSIFICATION.md)**: Player data classified as "Internal Use"
|
|
659
|
+
- **[Cryptography Policy](https://github.com/Hack23/ISMS-PUBLIC/blob/main/Cryptography_Policy.md)**: AES-256 encryption standards
|
|
660
|
+
|
|
661
|
+
---
|
|
662
|
+
|
|
663
|
+
**ํ๊ด์ ๊ธธ์ ๊ฑธ์ด๋ผ** - _Walk the Path of the Black Trigram with Data Precision_
|
|
664
|
+
|
|
665
|
+
This data model documentation ensures type-safe, performant, and culturally authentic representation of Korean martial arts combat mechanics through comprehensive TypeScript interfaces and immutable state management.
|
|
666
|
+
|
|
667
|
+
---
|
|
668
|
+
|
|
669
|
+
**๐ Document Control:**
|
|
670
|
+
**โ
Approved by:** James Pether Sรถrling, CEO
|
|
671
|
+
**๐ค Distribution:** Public
|
|
672
|
+
**๐ท๏ธ Classification:** [](https://github.com/Hack23/ISMS-PUBLIC/blob/main/CLASSIFICATION.md#confidentiality-levels) [](https://github.com/Hack23/ISMS-PUBLIC/blob/main/CLASSIFICATION.md#integrity-levels) [](https://github.com/Hack23/ISMS-PUBLIC/blob/main/CLASSIFICATION.md#availability-levels)
|
|
673
|
+
**๐
Effective Date:** 2026-03-19
|
|
674
|
+
**โฐ Next Review:** 2026-09-19
|
|
675
|
+
**๐ฏ Framework Compliance:** [](https://github.com/Hack23/ISMS-PUBLIC/blob/main/CLASSIFICATION.md) [](https://github.com/Hack23/ISMS-PUBLIC/blob/main/CLASSIFICATION.md)
|