Initial Commit

This commit is contained in:
2026-05-27 23:29:53 +01:00
commit fbc70f96e6
10000 changed files with 1102152 additions and 0 deletions

View File

@@ -0,0 +1,180 @@
# OpenSpec Change: enterprise-gaming-combat
- **Change ID**: enterprise-gaming-combat
- **Package**: `@suaveplan/combat`
- **Category**: gaming/combat
- **Target path**: `gaming/combat/combat`
- **Status**: PROPOSED
- **Date**: 2026-04-24
- **Reference spec**: `/mnt/s/web/suaveplan/enterprise/combat.md`
---
## Summary
Deliver `@suaveplan/combat` on the genesis branch from scratch at enterprise quality. The package provides core combat mechanics: multiple damage types (physical, elemental, true), health/armor/shield layers, resistances, status effects (burn, stun, slow, poison) with duration and tick logic, damage calculation pipeline with modifier chain, and `CombatManager` that processes hit events and emits `@suaveplan/events` combat messages. Genesis adds Zod schemas for all combat data, structured errors, OTel damage counters, injectable clock, and 100% coverage including property tests for damage pipeline commutativity.
---
## Current-state audit (genesis)
Package does not exist on genesis yet — fresh build.
---
## Available workspace deps on genesis
| Package | Role |
|---|---|
| `@suaveplan/error` (`workspace:^`) | `CombatError`; `COMBAT.*` codes |
| `@suaveplan/types` (`workspace:^`) | `Clock`, `IdGenerator` |
| `@suaveplan/events` (`workspace:^`) | `combat:hit`, `combat:death`, `combat:status` events |
| `zod` (`catalog:forms`) | `DamageEvent`, `StatusEffect`, `CombatantStats` schemas |
| `@opentelemetry/api` (`catalog:observability`) | Damage counter, death counter |
---
## Public API surface
```ts
type DamageType = 'physical' | 'fire' | 'ice' | 'lightning' | 'poison' | 'true'
interface CombatantStats {
maxHealth: number
maxArmor: number
maxShield: number
resistances: Partial<Record<DamageType, number>> // 0–1 reduction
defense: number
}
function createCombatant(id: string, stats: CombatantStats): Combatant
interface Combatant {
readonly id: string
readonly health: number
readonly armor: number
readonly shield: number
readonly isDead: boolean
readonly statusEffects: readonly StatusEffect[]
applyDamage(event: DamageEvent): DamageResult
applyHealing(amount: number, type?: 'health' | 'shield'): void
applyStatus(effect: StatusEffect): void
tick(dt: number): void // processes status effect durations + ticks
revive(health?: number): void
}
interface DamageEvent {
sourceId: string
targetId: string
amount: number
type: DamageType
isCritical?: boolean
modifiers?: DamageModifier[]
}
interface DamageResult {
finalDamage: number
healthDamage: number
armorDamage: number
shieldDamage: number
wasKilled: boolean
statusesApplied: string[]
}
interface StatusEffect {
id: string
name: string
duration: number
tickInterval?: number
tickDamage?: number
tickDamageType?: DamageType
speedModifier?: number
damageModifier?: number
}
interface DamageModifier {
type: 'multiply' | 'add' | 'set'
value: number
priority?: number
}
function createCombatManager(options?: CombatManagerOptions): CombatManager
interface CombatManager {
registerCombatant(combatant: Combatant): void
unregisterCombatant(id: string): void
processHit(event: DamageEvent): DamageResult
tick(dt: number): void
getCombatant(id: string): Combatant | undefined
}
```
### Error codes
```ts
type CombatErrorCode =
| 'COMBAT_COMBATANT_NOT_FOUND'
| 'COMBAT_TARGET_DEAD'
| 'COMBAT_INVALID_DAMAGE'
| 'COMBAT_STATUS_OVERFLOW'
```
---
## New additions for genesis
1. **Damage pipeline** — ordered modifier chain: resistances → armor absorption → shield drain → health damage.
2. **Status effect stacking** — configurable max-stack count; refresh vs. stack vs. replace policy.
3. **Critical hit multiplier** — `isCritical` doubles damage before modifier chain.
4. **OTel** — `combat.damage_total` counter (by type); `combat.deaths_total` counter; `combat.active_combatants` gauge.
---
## File layout
```text
gaming/combat/combat/
package.json
tsconfig.json
vitest.config.ts
src/
index.ts
error-codes.ts
constants/index.ts
types/common.ts
types/common.md
core/
combatant/
combatant.ts
combatant.md
combatant.types.ts
combatant.test.ts
index.ts
damage-pipeline/
damage-pipeline.ts
damage-pipeline.md
damage-pipeline.types.ts
damage-pipeline.test.ts
index.ts
status-effect/
status-effect.ts
status-effect.md
status-effect.types.ts
status-effect.test.ts
index.ts
combat-manager/
combat-manager.ts
combat-manager.md
combat-manager.types.ts
combat-manager.test.ts
index.ts
tests/
integration.test.ts
property.test.ts
```
---
## Impact
**Downstream**: `@suaveplan/weapons` feeds damage events into combat manager; `@suaveplan/r3f-combat` renders damage numbers. Prerequisites: `@suaveplan/error`, `@suaveplan/types`, `@suaveplan/events`.