Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 | 22x 36x 36x 53x 1x 52x 1x 51x 51x 53x 53x 53x 10x 51x 25x 26x 21x 1x 2x 1x 1x 21x 1x 1x 1x | /**
* Combat Injury Integration
*
* **Korean**: 전투 부상 통합
*
* Integrates InjuryTracker with combat damage events to automatically
* record injuries and trigger visual trauma effects during combat.
*
* @module systems/bodypart/CombatInjuryIntegration
* @category Body Part System
* @korean 전투부상통합
*/
import * as THREE from "three";
import { BodyRegion, DamageType } from "../../types/common";
import { InjuryTracker } from "./InjuryTracker";
import {
getInjuryPositionWithOffset,
mapBodyRegionToBodyPart,
} from "./BodyPartPositionMapping";
import { InjuryType } from "../../types/injury";
/**
* Combat damage event data.
*
* **Korean**: 전투 피해 이벤트 데이터
*
* @public
*/
export interface CombatDamageEvent {
/** Damage amount (0-100) */
readonly damage: number;
/** Body region hit */
readonly bodyRegion: BodyRegion;
/** Damage type */
readonly damageType?: DamageType;
/** Optional specific position override */
readonly position?: THREE.Vector3;
/** Whether this is a critical hit */
readonly isCritical?: boolean;
}
/**
* Configuration for combat injury integration.
*
* @public
*/
export interface CombatInjuryConfig {
/** Enable automatic injury tracking */
readonly enabled: boolean;
/** Minimum damage to create injury */
readonly minDamage: number;
/** Damage threshold for blood effects */
readonly bloodThreshold: number;
/**
* InjuryTracker instance to use for this integration.
* Must be explicitly provided per character; singleton usage is no longer supported.
*/
readonly tracker: InjuryTracker;
}
/**
* Default combat injury configuration.
*
* Note: A valid `tracker` must still be supplied by the caller.
* This provides defaults for other configuration values only.
*
* @public
*/
export const DEFAULT_COMBAT_INJURY_CONFIG: Omit<CombatInjuryConfig, 'tracker'> = {
enabled: true,
minDamage: 5,
bloodThreshold: 30,
} as const;
/**
* Combat Injury Integration Handler.
*
* **Korean**: 전투 부상 통합 핸들러
*
* Processes combat damage events and records injuries for visualization.
* Automatically maps damage types to injury types and applies blood effects.
*
* @example
* ```typescript
* // Recommended: Use PlayerInjuryTrackingManager for per-player tracking
* import { playerInjuryManager } from '@/systems/bodypart';
* const integration = playerInjuryManager.getIntegrationForPlayer('player-1');
*
* // Or create with explicit tracker for testing/custom scenarios
* const handler = new CombatInjuryIntegration({
* ...DEFAULT_COMBAT_INJURY_CONFIG,
* tracker: new InjuryTracker(),
* });
*
* // Record combat damage
* handler.recordCombatDamage({
* damage: 35,
* bodyRegion: BodyRegion.TORSO,
* damageType: DamageType.BLUNT,
* });
*
* // Get injuries for visualization
* const injuries = handler.getInjuries();
* ```
*
* @public
*/
export class CombatInjuryIntegration {
private tracker: InjuryTracker;
private config: CombatInjuryConfig;
constructor(config: CombatInjuryConfig) {
this.config = config;
// Tracker is now required in CombatInjuryConfig interface
this.tracker = config.tracker;
}
/**
* Record injury from combat damage event.
*
* **Korean**: 전투 피해로부터 부상 기록
*
* Automatically determines injury type from damage type and applies
* appropriate visual effects.
*
* @param event - Combat damage event
* @returns Whether injury was recorded (false if damage too low)
*
* @public
*/
recordCombatDamage(event: CombatDamageEvent): boolean {
if (!this.config.enabled) {
return false;
}
if (event.damage < this.config.minDamage) {
return false;
}
// Determine injury type from damage type
const injuryType = this.getInjuryTypeFromDamage(event.damageType);
// Get position for injury
const position =
event.position ?? getInjuryPositionWithOffset(event.bodyRegion, 0.15);
// Map body region to body part
const bodyPart = mapBodyRegionToBodyPart(event.bodyRegion);
// Record injury
const recordedInjury = this.tracker.recordInjury(
bodyPart,
event.bodyRegion,
position,
event.damage,
injuryType
);
// Return true only if the injury was actually recorded
return recordedInjury !== null;
}
/**
* Check if damage should trigger blood effects.
*
* **Korean**: 피해가 출혈 효과를 발생시켜야 하는지 확인
*
* @param damage - Damage amount
* @returns Whether to show blood effects
*
* @public
*/
shouldShowBloodEffect(damage: number): boolean {
return damage > this.config.bloodThreshold;
}
/**
* Get injury type from damage type.
*
* **Korean**: 피해 타입으로부터 부상 타입 가져오기
*
* @param damageType - Type of damage dealt
* @returns Corresponding injury type for visualization
*
* @private
*/
private getInjuryTypeFromDamage(damageType?: DamageType): InjuryType {
if (!damageType) {
return InjuryType.BRUISE; // Default to bruise
}
switch (damageType) {
case DamageType.BLUNT:
case DamageType.IMPACT:
case DamageType.CRUSHING:
return InjuryType.BRUISE;
case DamageType.PIERCING:
case DamageType.SHARP:
return InjuryType.CUT;
case DamageType.SLASHING:
return InjuryType.LACERATION;
case DamageType.JOINT:
return InjuryType.FRACTURE;
default:
return InjuryType.BRUISE;
}
}
/**
* Get all tracked injuries.
*
* **Korean**: 모든 추적된 부상 가져오기
*
* @returns Array of injuries
*
* @public
*/
getInjuries() {
return this.tracker.getInjuries();
}
/**
* Get tracker instance.
*
* @returns InjuryTracker instance
*
* @public
*/
getTracker(): InjuryTracker {
return this.tracker;
}
/**
* Clear all injuries (for new round/match).
*
* **Korean**: 모든 부상 초기화
*
* @public
*/
clearInjuries(): void {
this.tracker.clearInjuries();
}
/**
* Remove expired injuries.
*
* **Korean**: 만료된 부상 제거
*
* @public
*/
removeExpiredInjuries(): void {
this.tracker.removeExpiredInjuries();
}
}
/**
* @deprecated Use {@link PlayerInjuryTrackingManager} instead to get per-player instances.
*
* Creating a singleton is no longer supported because it mixes injuries between
* multiple characters. Use `playerInjuryManager.getIntegrationForPlayer(playerId)`
* to get a properly scoped integration instance.
*
* **Korean**: PlayerInjuryTrackingManager를 사용하여 플레이어별 인스턴스를 가져오세요
*
* @example
* ```typescript
* // OLD (deprecated):
* // import { combatInjuryIntegration } from '@/systems/bodypart';
*
* // NEW (correct):
* import { playerInjuryManager } from '@/systems/bodypart';
* const integration = playerInjuryManager.getIntegrationForPlayer(playerId);
* ```
*
* @public
*/
// Singleton export removed - use PlayerInjuryTrackingManager instead
|