@adatechnology/game-characters 0.1.5 → 0.2.0
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 +28 -0
- package/dist/index.d.ts +102 -1
- package/dist/index.global.js +514 -2
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +514 -2
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/data/body.json","../src/body/body-spec.ts","../src/corpses.ts","../src/body/body-state.ts","../src/presets/team-game.json","../src/body/regions.ts","../src/data/segments.json","../src/body/segment-tree.ts","../src/body/describe.ts","../src/body/object-state.ts","../src/body/rig.ts","../src/character.ts","../src/body/transform.ts","../src/damage/bleeding.ts","../src/damage/body-ops.ts","../src/presets/physical.json","../src/damage/defaults.ts","../src/damage/penetration.ts","../src/damage/rules/blow.ts","../src/damage/rules/regions.ts","../src/damage/points.ts","../src/damage/blast.ts","../src/damage/protection.ts","../src/damage/resolve-part.ts","../src/damage/rules/arsenal.ts","../src/damage/rules/elenco.ts","../src/damage/rules/kit.ts","../src/damage/pipeline.ts","../src/damage/damage-character.ts","../src/damage/line.ts","../src/registry.ts","../src/kit.ts","../src/data/gait.json","../src/gait/stride.ts","../src/gait/profile.ts","../src/gait/animate.ts","../src/gait/cascade.ts","../src/gait/moves.ts","../src/gait/lying.ts","../src/condition/timeline.ts","../src/data/appearance.json","../src/appearance/variance.ts","../src/appearance/palette.ts","../src/appearance/traits.ts"],"sourcesContent":["{\n \"guide\": {\n \"heightMetres\": 1.8,\n \"shoulderWidthMetres\": 0.61,\n \"shoulderWidthWomanMetres\": 0.57,\n \"shoulderHeightMetres\": 1.475,\n \"headToHeight\": 0.1667\n },\n \"teamGame\": {\n \"source\": \"G 65336 J (shoulders +-0.24 m)\",\n \"joints\": {\n \"quadril\": [\n 0,\n 0.95,\n 0\n ],\n \"pescoco\": [\n 0,\n 1.52,\n 0\n ],\n \"ombroE\": [\n -0.24,\n 1.44,\n 0\n ],\n \"ombroD\": [\n 0.24,\n 1.44,\n 0\n ],\n \"cotoveloE\": [\n -0.27,\n 1.13,\n 0\n ],\n \"cotoveloD\": [\n 0.27,\n 1.13,\n 0\n ],\n \"coxaE\": [\n -0.1,\n 0.92,\n 0\n ],\n \"coxaD\": [\n 0.1,\n 0.92,\n 0\n ],\n \"joelhoE\": [\n -0.1,\n 0.5,\n 0\n ],\n \"joelhoD\": [\n 0.1,\n 0.5,\n 0\n ]\n },\n \"heightMetres\": 1.8\n },\n \"lodDistancesMetres\": [\n 18,\n 55\n ],\n \"triangleBudget\": {\n \"lod0\": 2500,\n \"lod1\": 800,\n \"lod2\": 250\n }\n}\n","import type { SegmentKind, Vec3 } from '@adatechnology/game-contracts'\n\nimport body from '../data/body.json'\n\n/** The 17 joints of a body: one per segment, the point the segment hangs from. */\nexport type JointId =\n | 'hip'\n | 'spine'\n | 'neck'\n | 'head'\n | 'jaw'\n | 'shoulderL'\n | 'shoulderR'\n | 'elbowL'\n | 'elbowR'\n | 'wristL'\n | 'wristR'\n | 'hipL'\n | 'hipR'\n | 'kneeL'\n | 'kneeR'\n | 'ankleL'\n | 'ankleR'\n\nexport const JOINT_IDS: readonly JointId[] = ['hip', 'spine', 'neck', 'head', 'jaw', 'shoulderL', 'shoulderR', 'elbowL', 'elbowR', 'wristL', 'wristR', 'hipL', 'hipR', 'kneeL', 'kneeR', 'ankleL', 'ankleR']\n\n/**\n * Proportions of a body: joint positions in metres for a body of `heightMetres`, standing, feet on y = 0, facing +z, left side on +x.\n * `segmentRadius` is the radius of the capsule a segment is hit through.\n */\nexport type BodySpec = {\n readonly id: string\n readonly heightMetres: number\n readonly joints: Readonly<Record<JointId, Vec3>>\n readonly segmentRadius: Readonly<Record<SegmentKind, number>>\n}\n\nconst SEGMENT_RADIUS: Readonly<Record<SegmentKind, number>> = {\n head: 0.1,\n jaw: 0.05,\n neck: 0.06,\n torso: 0.17,\n pelvis: 0.16,\n upperArm: 0.085,\n forearm: 0.065,\n hand: 0.05,\n thigh: 0.1,\n shin: 0.08,\n foot: 0.05,\n}\n\nconst { guide } = body\nconst shoulderX = guide.shoulderWidthMetres / 2\nconst shoulderY = guide.shoulderHeightMetres\n\n/** The Elenco style guide body (1.80 m, shoulders 0.61 m at 1.475 m, head about 1/6 of the height): the default. */\nexport const GUIDE: BodySpec = {\n id: 'guide',\n heightMetres: guide.heightMetres,\n joints: {\n hip: [0, 0.92, 0],\n spine: [0, 1.05, 0],\n neck: [0, 1.56, 0],\n head: [0, 1.64, 0],\n jaw: [0, 1.66, 0.06],\n shoulderL: [shoulderX, shoulderY, 0],\n shoulderR: [-shoulderX, shoulderY, 0],\n elbowL: [shoulderX, shoulderY - 0.31, 0],\n elbowR: [-shoulderX, shoulderY - 0.31, 0],\n wristL: [shoulderX, shoulderY - 0.61, 0],\n wristR: [-shoulderX, shoulderY - 0.61, 0],\n hipL: [0.105, 0.9, 0],\n hipR: [-0.105, 0.9, 0],\n kneeL: [0.105, 0.48, 0],\n kneeR: [-0.105, 0.48, 0],\n ankleL: [0.105, 0.1, 0],\n ankleR: [-0.105, 0.1, 0],\n },\n segmentRadius: SEGMENT_RADIUS,\n}\n\nconst J = body.teamGame.joints\nconst below = (point: readonly number[], drop: number): Vec3 => [point[0], point[1] - drop, point[2]]\n\n/**\n * The game's crowd body (G 65336 `J`, shoulders ±0.24 m), kept for the goldens of the instanced path. `J` has no spine, head, jaw, wrist or\n * ankle: spine and head sit on the hip and neck bones (bones 0 and 1 of the game), the wrist and ankle one forearm and one shin below.\n */\nexport const TEAM_GAME: BodySpec = {\n id: 'team-game',\n heightMetres: body.teamGame.heightMetres,\n joints: {\n hip: J.quadril as Vec3,\n spine: J.quadril as Vec3,\n neck: J.pescoco as Vec3,\n head: J.pescoco as Vec3,\n jaw: [0, J.pescoco[1] + 0.08, 0.06],\n shoulderL: J.ombroE as Vec3,\n shoulderR: J.ombroD as Vec3,\n elbowL: J.cotoveloE as Vec3,\n elbowR: J.cotoveloD as Vec3,\n wristL: below(J.cotoveloE, 0.3),\n wristR: below(J.cotoveloD, 0.3),\n hipL: J.coxaE as Vec3,\n hipR: J.coxaD as Vec3,\n kneeL: J.joelhoE as Vec3,\n kneeR: J.joelhoD as Vec3,\n ankleL: below(J.joelhoE, 0.42),\n ankleR: below(J.joelhoD, 0.42),\n },\n segmentRadius: SEGMENT_RADIUS,\n}\n\n/** A body spec from `base` (default `GUIDE`) with the given fields replaced; `joints` and `segmentRadius` merge key by key. */\nexport const createBodySpec = (patch: Partial<BodySpec> = {}, base: BodySpec = GUIDE): BodySpec => ({\n id: patch.id ?? base.id,\n heightMetres: patch.heightMetres ?? base.heightMetres,\n joints: { ...base.joints, ...patch.joints },\n segmentRadius: { ...base.segmentRadius, ...patch.segmentRadius },\n})\n","import type { CorpseOptions } from './types'\n\nexport type CorpseEntry<TData> = {\n /** Seconds since it fell. */\n age: number\n readonly data: TData\n}\n\nexport type CorpseLedger<TData> = {\n readonly entries: readonly CorpseEntry<TData>[]\n readonly count: number\n /** Adds a corpse; when the ledger is full the oldest one is replaced. Returns the replaced data, if any. */\n add(data: TData): TData | undefined\n /** Ages every corpse by `dt` seconds and removes the ones past their life (swap with the last, like the game). Returns the removed data. */\n update(dt: number): TData[]\n clear(): void\n}\n\n/** The bodies left on the ground: capped (400) and gone after a lifetime (900 s); generic over what each one carries. */\nexport const createCorpseLedger = <TData>(options: CorpseOptions): CorpseLedger<TData> => {\n const entries: CorpseEntry<TData>[] = []\n return {\n entries,\n get count() {\n return entries.length\n },\n add(data) {\n if (entries.length < options.max) {\n entries.push({ age: 0, data })\n return undefined\n }\n let oldest = 0\n for (let index = 1; index < entries.length; index++) if ((entries[index] as CorpseEntry<TData>).age > (entries[oldest] as CorpseEntry<TData>).age) oldest = index\n const replaced = (entries[oldest] as CorpseEntry<TData>).data\n entries[oldest] = { age: 0, data }\n return replaced\n },\n update(dt) {\n const removed: TData[] = []\n for (let index = 0; index < entries.length; index++) {\n const entry = entries[index] as CorpseEntry<TData>\n entry.age += dt\n if (entry.age <= options.seconds) continue\n removed.push(entry.data)\n entries[index] = entries[entries.length - 1] as CorpseEntry<TData>\n entries.pop()\n index--\n }\n return removed\n },\n clear() {\n entries.length = 0\n },\n }\n}\n","import { MISSING_BITS } from '@adatechnology/game-contracts'\nimport type { SegmentKind } from '@adatechnology/game-contracts'\n\nimport type { Detail, SegmentState } from '../types'\nimport { LIMB_REGIONS, REGION_HIT_POINTS, REGION_SEGMENTS } from './regions'\nimport type { LimbRegion } from './regions'\nimport { SEGMENT_TREE } from './segment-tree'\nimport type { SegmentId, SegmentSide } from './segment-tree'\n\n/** The mutable state of one body. Both detail levels live here: the 17 segments and the hit points of the 5 crowd regions. */\nexport type BodyState = {\n readonly segments: SegmentState[]\n readonly regions: Record<LimbRegion, number>\n vitality: number\n readonly maxVitality: number\n alive: boolean\n /** The game's `MISSING_BITS` mask. */\n missing: number\n /** Sides that limp, in the order they started. */\n readonly limping: SegmentSide[]\n crawl: boolean\n stunSeconds: number\n /** Loose pieces: each severed segment with what fell with it. */\n readonly pieces: SegmentId[][]\n /** Protection layers used up (a helmet that took its one shot). */\n readonly consumed: Set<string>\n detail: Detail\n}\n\nexport type CreateBodyStateParams = { readonly vitality: number; readonly detail: Detail; readonly crawling?: boolean; readonly hitPointsOf: (kind: SegmentKind) => number }\n\nexport const createBodyState = ({ vitality, detail, crawling, hitPointsOf }: CreateBodyStateParams): BodyState => ({\n segments: SEGMENT_TREE.map((node) => {\n const max = hitPointsOf(node.kind)\n return { id: node.id, kind: node.kind, region: node.region, hp: max, max, status: 'ok', attached: true, ...(node.side ? { side: node.side } : {}) }\n }),\n regions: { ...REGION_HIT_POINTS },\n vitality,\n maxVitality: vitality,\n alive: true,\n missing: 0,\n limping: [],\n crawl: crawling ?? false,\n stunSeconds: 0,\n pieces: [],\n consumed: new Set(),\n detail,\n})\n\nexport const segmentOf = (body: BodyState, id: SegmentId): SegmentState => {\n const segment = body.segments.find((candidate) => candidate.id === id)\n if (!segment) throw new Error(`game-characters: unknown segment \"${id}\"`)\n return segment\n}\n\nconst LIMB_MASK: readonly { readonly ids: readonly SegmentId[]; readonly lost: number; readonly broken: number }[] = [\n { ids: ['upperArmL', 'forearmL'], lost: MISSING_BITS.armL, broken: MISSING_BITS.armLBroken },\n { ids: ['upperArmR', 'forearmR'], lost: MISSING_BITS.armR, broken: MISSING_BITS.armRBroken },\n { ids: ['thighL', 'shinL'], lost: MISSING_BITS.legL, broken: MISSING_BITS.legLBroken },\n { ids: ['thighR', 'shinR'], lost: MISSING_BITS.legR, broken: MISSING_BITS.legRBroken },\n]\n\n/** The crowd mask the segments amount to: a lost head, jaw, arm or leg (upper or lower part), and a broken one still attached. */\nexport const missingFromSegments = (body: BodyState): number => {\n let mask = 0\n if (!segmentOf(body, 'head').attached) mask |= MISSING_BITS.head\n else if (!segmentOf(body, 'jaw').attached) mask |= MISSING_BITS.jaw\n for (const limb of LIMB_MASK) {\n const parts = limb.ids.map((id) => segmentOf(body, id))\n if (parts.some((part) => !part.attached)) mask |= limb.lost\n else if (parts.some((part) => part.status === 'broken')) mask |= limb.broken\n }\n return mask\n}\n\n/** Region hit points from the segments: the share of the region's segment hit points left, scaled to the region's own hit points. */\nexport const regionsFromSegments = (body: BodyState): void => {\n for (const region of LIMB_REGIONS) {\n const parts = REGION_SEGMENTS[region].map((id) => segmentOf(body, id))\n const left = parts.reduce((sum, part) => sum + (part.attached ? Math.max(0, part.hp) : 0), 0)\n const total = parts.reduce((sum, part) => sum + part.max, 0)\n body.regions[region] = (REGION_HIT_POINTS[region] * left) / total\n }\n body.missing |= missingFromSegments(body)\n}\n\n/** Segment hit points from the regions (the reverse is lossy: every segment of a region keeps the region's share). */\nexport const segmentsFromRegions = (body: BodyState): void => {\n for (const region of LIMB_REGIONS) {\n const share = Math.max(0, body.regions[region]) / REGION_HIT_POINTS[region]\n for (const id of REGION_SEGMENTS[region]) {\n const part = segmentOf(body, id)\n if (part.attached) part.hp = Math.min(part.hp, part.max * share)\n }\n }\n}\n","{\n \"id\": \"team-game\",\n \"segments\": {\n \"head\": 40,\n \"arm\": 60,\n \"leg\": 80\n },\n \"calibers\": {\n \"7_62x51\": {\n \"gameKey\": \"308\",\n \"name\": \"7,62×51 (.308)\",\n \"points\": 75,\n \"penetration\": 4,\n \"effectiveRangeMetres\": 600,\n \"noiseMetres\": 130,\n \"skullRange\": 1,\n \"class\": \"rifle\"\n },\n \"9x19\": {\n \"gameKey\": \"9x19\",\n \"name\": \"9×19 mm\",\n \"points\": 35,\n \"penetration\": 1.2,\n \"effectiveRangeMetres\": 35,\n \"noiseMetres\": 60,\n \"skullRange\": 1,\n \"class\": \"pistol\"\n },\n \"12ga_00buck\": {\n \"gameKey\": \"12ga\",\n \"name\": \"12 ga 00\",\n \"points\": 12,\n \"pellets\": 9,\n \"penetration\": 0.5,\n \"effectiveRangeMetres\": 15,\n \"noiseMetres\": 90,\n \"skullRange\": 8,\n \"class\": \"pistol\"\n },\n \"7_62x39\": {\n \"gameKey\": \"762x39\",\n \"name\": \"7,62×39 mm\",\n \"points\": 55,\n \"penetration\": 3,\n \"effectiveRangeMetres\": 250,\n \"noiseMetres\": 110,\n \"skullRange\": 1,\n \"class\": \"rifle\"\n }\n },\n \"regionCost\": {\n \"head\": 0.7,\n \"torso\": 1,\n \"bruteTorso\": 2,\n \"limb\": 0.5\n },\n \"damageKeptPerBody\": 0.75,\n \"falloff\": {\n \"fullAtRange\": 1,\n \"atTwiceRange\": 0.5\n },\n \"helmetAbsorbs\": \"pistol\",\n \"regions\": [\n \"head\",\n \"torso\",\n \"armL\",\n \"armR\",\n \"legL\",\n \"legR\"\n ]\n}\n","import type { BodyRegion } from '@adatechnology/game-contracts'\n\nimport teamGame from '../presets/team-game.json'\nimport type { SegmentId } from './segment-tree'\n\n/** The regions that keep their own hit points in the crowd model (the torso has none: torso hits go to vitality). */\nexport type LimbRegion = Exclude<BodyRegion, 'torso'>\n\nexport const LIMB_REGIONS: readonly LimbRegion[] = ['head', 'armL', 'armR', 'legL', 'legR']\n\n/** The game's region numbers (`SEG`): hit points of the head, of an arm and of a leg. */\nexport const REGION_HIT_POINTS: Readonly<Record<LimbRegion, number>> = {\n head: teamGame.segments.head,\n armL: teamGame.segments.arm,\n armR: teamGame.segments.arm,\n legL: teamGame.segments.leg,\n legR: teamGame.segments.leg,\n}\n\n/** The segments that make up each region, and the one that names it in events (the first). */\nexport const REGION_SEGMENTS: Readonly<Record<BodyRegion, readonly SegmentId[]>> = {\n head: ['head', 'jaw', 'neck'],\n torso: ['torso', 'pelvis'],\n armL: ['upperArmL', 'forearmL', 'handL'],\n armR: ['upperArmR', 'forearmR', 'handR'],\n legL: ['thighL', 'shinL', 'footL'],\n legR: ['thighR', 'shinR', 'footR'],\n}\n\nexport const BODY_REGIONS: readonly BodyRegion[] = ['head', 'torso', 'armL', 'armR', 'legL', 'legR']\n\nexport const isBodyRegion = (value: string): value is BodyRegion => (BODY_REGIONS as readonly string[]).includes(value)\n","{\n \"segments\": [\n {\n \"id\": \"head\",\n \"region\": \"head\",\n \"hitPoints\": 40,\n \"multiplier\": 3,\n \"bleed\": 40\n },\n {\n \"id\": \"jaw\",\n \"region\": \"head\",\n \"hitPoints\": 12,\n \"multiplier\": 2,\n \"bleed\": 8\n },\n {\n \"id\": \"neck\",\n \"region\": \"head\",\n \"hitPoints\": 25,\n \"multiplier\": 2,\n \"bleed\": 46\n },\n {\n \"id\": \"torso\",\n \"region\": \"torso\",\n \"hitPoints\": 150,\n \"multiplier\": 1,\n \"bleed\": 10\n },\n {\n \"id\": \"pelvis\",\n \"region\": \"torso\",\n \"hitPoints\": 90,\n \"multiplier\": 1,\n \"bleed\": 12\n },\n {\n \"id\": \"upperArm\",\n \"region\": \"arm\",\n \"hitPoints\": 45,\n \"multiplier\": 0.6,\n \"bleed\": 15\n },\n {\n \"id\": \"forearm\",\n \"region\": \"arm\",\n \"hitPoints\": 30,\n \"multiplier\": 0.6,\n \"bleed\": 8\n },\n {\n \"id\": \"hand\",\n \"region\": \"arm\",\n \"hitPoints\": 12,\n \"multiplier\": 0.6,\n \"bleed\": 3\n },\n {\n \"id\": \"thigh\",\n \"region\": \"leg\",\n \"hitPoints\": 55,\n \"multiplier\": 0.7,\n \"bleed\": 19\n },\n {\n \"id\": \"shin\",\n \"region\": \"leg\",\n \"hitPoints\": 40,\n \"multiplier\": 0.7,\n \"bleed\": 9\n },\n {\n \"id\": \"foot\",\n \"region\": \"leg\",\n \"hitPoints\": 15,\n \"multiplier\": 0.7,\n \"bleed\": 3\n }\n ],\n \"regions\": {\n \"head\": {\n \"hitPoints\": 40,\n \"segmentSum\": 77,\n \"scale\": 0.5195\n },\n \"arm\": {\n \"hitPoints\": 60,\n \"segmentSum\": 87,\n \"scale\": 0.6897\n },\n \"leg\": {\n \"hitPoints\": 80,\n \"segmentSum\": 110,\n \"scale\": 0.7273\n }\n },\n \"arsenalWeapons\": {\n \"pistola\": {\n \"n\": \"Pistola 9×19\",\n \"dmg\": 35,\n \"pel\": 1\n },\n \"fuzil\": {\n \"n\": \"Fuzil 7,62×39\",\n \"dmg\": 55,\n \"pel\": 1\n },\n \"escopeta\": {\n \"n\": \"Escopeta 12 ga\",\n \"dmg\": 12,\n \"pel\": 9\n },\n \"cinquenta\": {\n \"n\": \".50 BMG\",\n \"dmg\": 180,\n \"pel\": 1\n },\n \"granada\": {\n \"n\": \"Granada\",\n \"dmg\": 300,\n \"pel\": 0\n }\n },\n \"elenco\": {\n \"segments\": {\n \"head\": {\n \"hp\": 40,\n \"radius\": 0.07\n },\n \"torso\": {\n \"hp\": 120\n },\n \"pelvis\": {\n \"hp\": 90\n },\n \"upperArm\": {\n \"hp\": 60,\n \"radius\": 0.085\n },\n \"forearm\": {\n \"hp\": 45,\n \"radius\": 0.065\n },\n \"hand\": {\n \"hp\": 25,\n \"radius\": 0.05\n },\n \"thigh\": {\n \"hp\": 80,\n \"radius\": 0.1\n },\n \"shin\": {\n \"hp\": 55,\n \"radius\": 0.08\n }\n },\n \"below\": {\n \"upperArm\": [\n \"forearm\",\n \"hand\"\n ],\n \"forearm\": [\n \"hand\"\n ],\n \"thigh\": [\n \"shin\"\n ]\n },\n \"falls\": {\n \"upperArm\": \"o braço inteiro\",\n \"forearm\": \"o antebraço com a mão\",\n \"hand\": \"a mão\",\n \"thigh\": \"a perna inteira\",\n \"shin\": \"a canela com o pé\",\n \"head\": \"a cabeça\"\n },\n \"cutWeapons\": [\n {\n \"id\": \"faca\",\n \"n\": \"Faca\",\n \"dmg\": 22,\n \"cut\": 0.7\n },\n {\n \"id\": \"facao\",\n \"n\": \"Facão\",\n \"dmg\": 55,\n \"cut\": 1\n },\n {\n \"id\": \"machado\",\n \"n\": \"Machado\",\n \"dmg\": 85,\n \"cut\": 1\n },\n {\n \"id\": \"p9\",\n \"n\": \"Pistola 9 mm\",\n \"dmg\": 30,\n \"cut\": 0.15\n },\n {\n \"id\": \"e12\",\n \"n\": \"Espingarda 12\",\n \"dmg\": 95,\n \"cut\": 0.75\n },\n {\n \"id\": \"f762\",\n \"n\": \"Fuzil 7,62\",\n \"dmg\": 65,\n \"cut\": 0.45\n }\n ]\n },\n \"severity\": {\n \"severAtCut\": 0.5,\n \"severAtDamageFraction\": 0.9,\n \"destroyAtDamageMultiple\": 2,\n \"limpAtHpFraction\": 0.5,\n \"splitAtDamage\": 150,\n \"headKillDamage\": 20,\n \"jawChance\": 0.3,\n \"jawDamage\": 25,\n \"headBitDamage\": 60,\n \"headBitShotgunMetres\": 5\n },\n \"defaultCut\": {\n \"slash\": 0.85,\n \"blunt\": 0,\n \"explosive\": 1,\n \"ballistic\": {\n \"pistol\": 0.15,\n \"buckshot\": 0.75,\n \"rifle\": 0.45\n }\n },\n \"deathRule\": {\n \"default\": \"vitality-or-head\",\n \"options\": [\n \"vitality-or-head\",\n \"head-only\"\n ]\n }\n}\n","import type { BodyRegion, BodySlot, SegmentKind } from '@adatechnology/game-contracts'\n\nimport segments from '../data/segments.json'\nimport type { JointId } from './body-spec'\n\nexport type SegmentSide = 'L' | 'R'\ntype LimbKind = 'upperArm' | 'forearm' | 'hand' | 'thigh' | 'shin' | 'foot'\nexport type SegmentId = 'pelvis' | 'torso' | 'neck' | 'head' | 'jaw' | `${LimbKind}${SegmentSide}`\n\n/** One segment of the tree: the joint it hangs from, its parent, the crowd region it belongs to and the item slots that cover it. */\nexport type SegmentNode = {\n readonly id: SegmentId\n readonly kind: SegmentKind\n readonly side?: SegmentSide\n readonly joint: JointId\n readonly parent?: SegmentId\n readonly region: BodyRegion\n readonly slots: readonly BodySlot[]\n}\n\n/** Numbers of a segment kind (the Arsenal table, A4): hit points, damage multiplier and bleed rate. */\nexport type SegmentNumbers = { readonly hitPoints: number; readonly multiplier: number; readonly bleed: number }\n\nconst limb = (kind: LimbKind, side: SegmentSide, joint: JointId, parent: SegmentId | undefined, slots: readonly BodySlot[]): SegmentNode => {\n const isArm = kind === 'upperArm' || kind === 'forearm' || kind === 'hand'\n const region: BodyRegion = isArm ? (side === 'L' ? 'armL' : 'armR') : side === 'L' ? 'legL' : 'legR'\n return { id: `${kind}${side}`, kind, side, joint, region, slots, ...(parent ? { parent } : {}) }\n}\n\nconst sideOf = (side: SegmentSide): SegmentNode[] => [\n limb('upperArm', side, `shoulder${side}`, 'torso', ['arms']),\n limb('forearm', side, `elbow${side}`, `upperArm${side}`, ['arms']),\n limb('hand', side, `wrist${side}`, `forearm${side}`, ['hands']),\n limb('thigh', side, `hip${side}`, 'pelvis', ['legs']),\n limb('shin', side, `knee${side}`, `thigh${side}`, ['legs']),\n limb('foot', side, `ankle${side}`, `shin${side}`, ['feet']),\n]\n\n/** The 17 segments (11 kinds, limbs on both sides), parents before children. Neck and jaw have no item slot: a helmet does not cover them. */\nexport const SEGMENT_TREE: readonly SegmentNode[] = [\n { id: 'pelvis', kind: 'pelvis', joint: 'hip', region: 'torso', slots: ['torso'] },\n { id: 'torso', kind: 'torso', joint: 'spine', parent: 'pelvis', region: 'torso', slots: ['torso'] },\n { id: 'neck', kind: 'neck', joint: 'neck', parent: 'torso', region: 'head', slots: [] },\n { id: 'head', kind: 'head', joint: 'head', parent: 'neck', region: 'head', slots: ['head', 'eyes'] },\n { id: 'jaw', kind: 'jaw', joint: 'jaw', parent: 'head', region: 'head', slots: [] },\n ...sideOf('L'),\n ...sideOf('R'),\n]\n\nexport const SEGMENT_IDS: readonly SegmentId[] = SEGMENT_TREE.map((node) => node.id)\n\nconst NODES = new Map(SEGMENT_TREE.map((node) => [node.id, node]))\n\nexport const segmentNode = (id: SegmentId): SegmentNode => {\n const node = NODES.get(id)\n if (!node) throw new Error(`game-characters: unknown segment \"${id}\"`)\n return node\n}\n\nexport const isSegmentId = (value: string): value is SegmentId => NODES.has(value as SegmentId)\n\n/** Every segment that hangs below `id` (children, grandchildren...), in tree order: what falls with it when it is severed. */\nexport const segmentsBelow = (id: SegmentId): SegmentId[] => {\n const out: SegmentId[] = []\n const visit = (parent: SegmentId): void => {\n for (const node of SEGMENT_TREE) {\n if (node.parent !== parent) continue\n out.push(node.id)\n visit(node.id)\n }\n }\n visit(id)\n return out\n}\n\n/** The Arsenal numbers per segment kind (hit points, `MULT`, `BLEED`). */\nexport const SEGMENT_NUMBERS: Readonly<Record<SegmentKind, SegmentNumbers>> = Object.fromEntries(\n segments.segments.map((entry) => [entry.id, { hitPoints: entry.hitPoints, multiplier: entry.multiplier, bleed: entry.bleed }]),\n) as Record<SegmentKind, SegmentNumbers>\n","import type { DestructibleSpec, JointSpec, PartShape, PartSpec, SegmentKind, Vec3 } from '@adatechnology/game-contracts'\n\nimport type { BodySpec } from './body-spec'\nimport type { Rig } from './rig'\nimport { SEGMENT_TREE } from './segment-tree'\nimport type { SegmentNode } from './segment-tree'\n\n/** The material id the parts of a body carry (a destruction world without it skips its own material rules: the body is a `DestructibleImpl`). */\nexport const BODY_MATERIAL = 'flesh'\n\n/** Share of the body mass per segment kind (sums to 1 over the 17 segments). */\nconst MASS_SHARE: Readonly<Record<SegmentKind, number>> = {\n head: 0.07,\n jaw: 0.01,\n neck: 0.02,\n torso: 0.34,\n pelvis: 0.14,\n upperArm: 0.028,\n forearm: 0.016,\n hand: 0.006,\n thigh: 0.1,\n shin: 0.045,\n foot: 0.015,\n}\nconst ADULT_MASS_KG = 70\nconst LEAF_KINDS: ReadonlySet<SegmentKind> = new Set(['head', 'jaw', 'hand', 'foot'])\n\nconst firstChild = (node: SegmentNode): SegmentNode | undefined => SEGMENT_TREE.find((candidate) => candidate.parent === node.id)\n\n/** A cylinder from `from` to `to`: centred between them, its local +Y turned onto the segment (Euler XYZ). */\nconst cylinderBetween = (from: Vec3, to: Vec3, radius: number): { shape: PartShape; position: Vec3; rotation: Vec3 } => {\n const axis: Vec3 = [to[0] - from[0], to[1] - from[1], to[2] - from[2]]\n const length = Math.max(1e-3, Math.hypot(axis[0], axis[1], axis[2]))\n const [x, y, z] = [axis[0] / length, axis[1] / length, axis[2] / length]\n return {\n shape: { kind: 'cylinder', radius, height: length },\n position: [(from[0] + to[0]) / 2, (from[1] + to[1]) / 2, (from[2] + to[2]) / 2],\n rotation: [Math.atan2(z, y), 0, -Math.asin(Math.max(-1, Math.min(1, x)))],\n }\n}\n\nconst partOf = (node: SegmentNode, rig: Rig, body: BodySpec, massKg: number): PartSpec => {\n const joint = rig.joints[node.joint]\n const radius = body.segmentRadius[node.kind] * (rig.height / body.heightMetres)\n const mass = massKg * MASS_SHARE[node.kind]\n const child = firstChild(node)\n if (LEAF_KINDS.has(node.kind) || !child) {\n const lift = node.kind === 'head' ? radius : node.kind === 'jaw' ? 0 : -radius\n return { id: node.id, material: BODY_MATERIAL, shape: { kind: 'sphere', radius }, position: [joint[0], joint[1] + lift, joint[2]], mass, tags: ['body', node.kind] }\n }\n const placed = cylinderBetween(joint, rig.joints[child.joint], radius)\n return { id: node.id, material: BODY_MATERIAL, ...placed, mass, tags: ['body', node.kind] }\n}\n\nexport type DescribeBodyParams = { readonly rig: Rig; readonly body: BodySpec; readonly build: number; readonly name?: string }\n\n/** The body as destruction parts (one per segment, in the body's local space) and the joints between them. */\nexport const describeBody = ({ rig, body, build, name }: DescribeBodyParams): DestructibleSpec => {\n const massKg = ADULT_MASS_KG * (rig.height / body.heightMetres) ** 3 * build\n const parts = SEGMENT_TREE.map((node) => partOf(node, rig, body, massKg))\n const joints: JointSpec[] = SEGMENT_TREE.filter((node) => node.parent).map((node) => ({ id: `${node.parent}~${node.id}`, a: node.parent as string, b: node.id, kind: 'fused', tools: [] }))\n return { ...(name ? { name } : {}), parts, joints, tags: ['character'] }\n}\n","import type { DestructibleSpec, JointState, ObjectState, PartState, PartStatus, Quat, Vec3 } from '@adatechnology/game-contracts'\n\nimport type { SegmentStatus } from '../types'\nimport { missingFromSegments } from './body-state'\nimport type { BodyState } from './body-state'\n\nconst PART_STATUS: Readonly<Record<SegmentStatus, PartStatus>> = { ok: 'intact', wounded: 'damaged', broken: 'damaged', severed: 'collapsed', destroyed: 'broken' }\nconst BODY_TEMPERATURE_C = 37\n\nexport type ToObjectStateParams = {\n readonly id: string\n readonly name?: string\n readonly position: Vec3\n readonly rotation: Quat\n readonly body: BodyState\n readonly spec: DestructibleSpec\n}\n\n/** The body in the destruction contract: one part per segment, the joints between them, the pieces and the `body` summary. */\nexport const toObjectState = ({ id, name, position, rotation, body, spec }: ToObjectStateParams): ObjectState => {\n const groups: string[][] = [body.segments.filter((segment) => segment.attached).map((segment) => segment.id)]\n for (const piece of body.pieces) {\n const left = piece.filter((part) => body.segments.find((segment) => segment.id === part)?.status !== 'destroyed')\n if (left.length > 0) groups.push(left)\n }\n const groupOf = (part: string): number => groups.findIndex((group) => group.includes(part))\n const parts: PartState[] = body.segments.map((segment) => {\n const mass = spec.parts.find((part) => part.id === segment.id)?.mass ?? 0\n return {\n id: segment.id,\n material: 'flesh',\n status: PART_STATUS[segment.status],\n hp: Math.max(0, segment.hp),\n maxHp: segment.max,\n mass,\n temperature: BODY_TEMPERATURE_C,\n burning: false,\n fuel: 0,\n char: 0,\n melt: 0,\n dents: [],\n holes: [],\n cracks: [],\n group: groupOf(segment.id),\n }\n })\n const joints: JointState[] = (spec.joints ?? []).map((joint) => {\n const child = body.segments.find((segment) => segment.id === joint.b)\n const parent = body.segments.find((segment) => segment.id === joint.a)\n const open = child !== undefined && parent !== undefined && parent.attached !== child.attached\n return { id: joint.id ?? `${joint.a}~${joint.b}`, a: joint.a, b: joint.b, kind: joint.kind, hp: open ? 0 : 1, maxHp: 1, progress: 0, open, ...(open ? { openedBy: 'break' as const } : {}) }\n })\n return {\n id,\n ...(name ? { name } : {}),\n position: [...position],\n rotation: [...rotation],\n parts,\n joints,\n groups,\n destroyed: false,\n body: { alive: body.alive, vitality: body.vitality, missing: body.detail === 'segments' ? body.missing | missingFromSegments(body) : body.missing, limp: body.limping.length > 0, crawl: body.crawl },\n }\n}\n","import type { Vec3 } from '@adatechnology/game-contracts'\n\nimport { JOINT_IDS } from './body-spec'\nimport type { BodySpec, JointId } from './body-spec'\n\n/** The bones of the game's instanced body (G 65336): 0 torso and hip, 1 head, 2/3 arms, 4/5 thighs, 6 eyes, 7/8 forearms, 9/10 shins, 11 jaw. */\nexport const GAME_BONES = {\n torso: 0,\n head: 1,\n upperArmL: 2,\n upperArmR: 3,\n thighL: 4,\n thighR: 5,\n eyes: 6,\n forearmL: 7,\n forearmR: 8,\n shinL: 9,\n shinR: 10,\n jaw: 11,\n} as const\n\nexport const JOINT_PARENTS: Readonly<Record<JointId, JointId | undefined>> = {\n hip: undefined,\n spine: 'hip',\n neck: 'spine',\n head: 'neck',\n jaw: 'head',\n shoulderL: 'spine',\n shoulderR: 'spine',\n elbowL: 'shoulderL',\n elbowR: 'shoulderR',\n wristL: 'elbowL',\n wristR: 'elbowR',\n hipL: 'hip',\n hipR: 'hip',\n kneeL: 'hipL',\n kneeR: 'hipR',\n ankleL: 'kneeL',\n ankleR: 'kneeR',\n}\n\n/** The joints of one body, scaled to its height and build. */\nexport type Rig = {\n readonly joints: Readonly<Record<JointId, Vec3>>\n readonly parents: Readonly<Record<JointId, JointId | undefined>>\n readonly gameBones: typeof GAME_BONES\n /** Height in metres of this body. */\n readonly height: number\n}\n\nexport type CreateRigParams = { readonly body: BodySpec; readonly height: number; readonly build: number }\n\n/** Joints of `body` scaled to `height` metres (vertical and depth) and to `build` (width). */\nexport const createRig = ({ body, height, build }: CreateRigParams): Rig => {\n const scale = height / body.heightMetres\n const joints = Object.fromEntries(\n JOINT_IDS.map((id) => {\n const [x, y, z] = body.joints[id]\n return [id, [x * scale * build, y * scale, z * scale] as Vec3]\n }),\n ) as Record<JointId, Vec3>\n return { joints, parents: JOINT_PARENTS, gameBones: GAME_BONES, height }\n}\n","import type { DestructibleSpec, ObjectState, Quat, Vec3 } from '@adatechnology/game-contracts'\n\nimport type { BodySpec } from './body/body-spec'\nimport { createBodyState, regionsFromSegments, segmentsFromRegions } from './body/body-state'\nimport type { BodyState } from './body/body-state'\nimport { describeBody } from './body/describe'\nimport { toObjectState } from './body/object-state'\nimport type { LimbRegion } from './body/regions'\nimport { createRig } from './body/rig'\nimport type { Rig } from './body/rig'\nimport { SEGMENT_NUMBERS } from './body/segment-tree'\nimport type { BodyMultipliers, CharacterSpec, Detail, SegmentState } from './types'\n\n/** A spec with every default filled in. */\nexport type ResolvedCharacterSpec = CharacterSpec & {\n readonly id: string\n readonly height: number\n readonly build: number\n readonly vitality: number\n readonly multipliers: BodyMultipliers\n readonly limbFactor: number\n readonly bloodFactor: number\n readonly bodyCount: number\n readonly stunSeconds: number\n readonly protection: readonly string[]\n readonly detail: Detail\n}\n\nexport type Character = {\n readonly id: string\n readonly spec: ResolvedCharacterSpec\n readonly rig: Rig\n /** Live view of the 17 segments. */\n readonly segments: readonly SegmentState[]\n readonly detail: Detail\n /** Hit points of the 5 crowd regions (head, arms, legs). */\n regionHitPoints(): Readonly<Record<LimbRegion, number>>\n /** Swaps the detail level: segments to regions sums each region (lossless); regions to segments spreads the region's share (lossy). */\n setDetail(detail: Detail): void\n setTransform(position: Vec3, rotation?: Quat): void\n describe(): DestructibleSpec\n state(): ObjectState\n reset(): void\n}\n\nexport const DEFAULT_VITALITY = 100\nexport const DEFAULT_STUN_SECONDS = 0.45\nconst NO_MULTIPLIERS: BodyMultipliers = { head: 1, torso: 1, arms: 1, legs: 1 }\n\nexport const resolveSpec = (spec: CharacterSpec, body: BodySpec, counter: number): ResolvedCharacterSpec => ({\n ...spec,\n id: spec.id ?? `${spec.kind}_${counter}`,\n height: spec.height ?? body.heightMetres,\n build: spec.build ?? 1,\n vitality: spec.vitality ?? DEFAULT_VITALITY,\n multipliers: { ...NO_MULTIPLIERS, ...spec.multipliers },\n limbFactor: spec.limbFactor ?? 1,\n bloodFactor: spec.bloodFactor ?? 1,\n bodyCount: spec.bodyCount ?? 1,\n stunSeconds: spec.stunSeconds ?? DEFAULT_STUN_SECONDS,\n protection: spec.protection ?? [],\n detail: spec.detail ?? 'segments',\n})\n\nexport type CharacterCore = {\n readonly spec: ResolvedCharacterSpec\n readonly rig: Rig\n readonly body: BodyState\n position: Vec3\n rotation: Quat\n readonly describe: () => DestructibleSpec\n /** Back to the state at creation (full health, every segment attached). */\n readonly resetBody: () => void\n}\n\nexport type CreateCharacterCoreParams = { readonly spec: ResolvedCharacterSpec; readonly bodySpec: BodySpec; readonly hitPointsOf?: (kind: SegmentState['kind']) => number }\n\n/** The state every character shares: rig, body state, transform and the cached part list. */\nexport const createCharacterCore = ({ spec, bodySpec, hitPointsOf }: CreateCharacterCoreParams): CharacterCore => {\n const rig = createRig({ body: bodySpec, height: spec.height, build: spec.build })\n const parts = describeBody({ rig, body: bodySpec, build: spec.build, name: spec.kind })\n const fresh = (): BodyState => createBodyState({ vitality: spec.vitality, detail: spec.detail, crawling: spec.crawling ?? false, hitPointsOf: hitPointsOf ?? ((kind) => SEGMENT_NUMBERS[kind].hitPoints) })\n const body = fresh()\n return { spec, rig, body, position: [0, 0, 0], rotation: [0, 0, 0, 1], describe: () => parts, resetBody: () => void Object.assign(body, fresh()) }\n}\n\n/** The plain-data part of a character (state, detail and transform); the damage model is added on top of it. */\nexport const characterView = (core: CharacterCore): Character => ({\n id: core.spec.id,\n spec: core.spec,\n rig: core.rig,\n get segments() {\n return core.body.segments\n },\n get detail() {\n return core.body.detail\n },\n regionHitPoints: () => ({ ...core.body.regions }),\n setDetail(detail) {\n if (detail === core.body.detail) return\n if (detail === 'regions') regionsFromSegments(core.body)\n else segmentsFromRegions(core.body)\n core.body.detail = detail\n },\n setTransform(position, rotation) {\n core.position = [...position]\n if (rotation) core.rotation = [...rotation]\n },\n describe: core.describe,\n state: () => toObjectState({ id: core.spec.id, name: core.spec.kind, position: core.position, rotation: core.rotation, body: core.body, spec: core.describe() }),\n reset: core.resetBody,\n})\n","import type { Quat, Vec3 } from '@adatechnology/game-contracts'\n\n/** `v` rotated by the unit quaternion `q`. */\nexport const rotate = (q: Quat, v: Vec3): Vec3 => {\n const [x, y, z, w] = q\n const tx = 2 * (y * v[2] - z * v[1])\n const ty = 2 * (z * v[0] - x * v[2])\n const tz = 2 * (x * v[1] - y * v[0])\n return [v[0] + w * tx + (y * tz - z * ty), v[1] + w * ty + (z * tx - x * tz), v[2] + w * tz + (x * ty - y * tx)]\n}\n\nconst conjugate = (q: Quat): Quat => [-q[0], -q[1], -q[2], q[3]]\n\nexport type Transform = { readonly position: Vec3; readonly rotation: Quat }\n\nexport const toWorld = ({ position, rotation }: Transform, local: Vec3): Vec3 => {\n const turned = rotate(rotation, local)\n return [turned[0] + position[0], turned[1] + position[1], turned[2] + position[2]]\n}\n\nexport const toLocal = ({ position, rotation }: Transform, world: Vec3): Vec3 => rotate(conjugate(rotation), [world[0] - position[0], world[1] - position[1], world[2] - position[2]])\n\nexport const distance = (a: Vec3, b: Vec3): number => Math.hypot(a[0] - b[0], a[1] - b[1], a[2] - b[2])\n","import type { DestructionEvent, Vec3 } from '@adatechnology/game-contracts'\n\nimport type { SegmentId } from '../body/segment-tree'\n\n/** A bleeding wound: `rate` in drops per second (the Arsenal's unit) fading to 0 over `duration` seconds; `spurt` pulses like an artery. */\nexport type Bleeder = {\n readonly part: SegmentId\n readonly rate: number\n readonly duration: number\n readonly spurt: boolean\n age: number\n /** Whole seconds of this bleeder already reported as `leak` events. */\n reported: number\n}\n\n/** Volume of one drop (a 4 mm drop of the Arsenal's blood): `leak` events carry litres per second. */\nexport const BLOOD_LITERS_PER_DROP = 0.00027\n\nexport const bleedRateAt = (bleeder: Bleeder): number => (bleeder.age >= bleeder.duration ? 0 : bleeder.rate * (1 - bleeder.age / bleeder.duration))\n\nexport type StepBleedingParams = {\n readonly bleeders: Bleeder[]\n readonly dt: number\n readonly emit: (event: Omit<Extract<DestructionEvent, { type: 'leak' }>, 'object' | 'time'>) => void\n readonly pointOf: (id: SegmentId) => Vec3\n}\n\n/** Ages the bleeders; each one still running reports a `leak` with its current rate once per second of its life. */\nexport const stepBleeding = ({ bleeders, dt, emit, pointOf }: StepBleedingParams): void => {\n for (const bleeder of bleeders) {\n if (bleeder.age >= bleeder.duration) continue\n bleeder.age += dt\n const second = Math.floor(bleeder.age)\n if (second <= bleeder.reported) continue\n bleeder.reported = second\n const rate = bleedRateAt(bleeder)\n if (rate > 0) emit({ type: 'leak', part: bleeder.part, fluid: 'blood', point: pointOf(bleeder.part), direction: [0, -1, 0], rate: rate * BLOOD_LITERS_PER_DROP, pressurized: bleeder.spurt })\n }\n}\n","import type { DamageType, DestructionEvent, Vec3 } from '@adatechnology/game-contracts'\n\nimport type { BodyState } from '../body/body-state'\nimport { segmentOf } from '../body/body-state'\nimport { segmentNode, segmentsBelow } from '../body/segment-tree'\nimport type { SegmentId, SegmentSide } from '../body/segment-tree'\nimport type { ResolvedCharacterSpec } from '../character'\nimport type { SegmentState } from '../types'\nimport { BLOOD_LITERS_PER_DROP } from './bleeding'\nimport type { Bleeder } from './bleeding'\nimport type { DamageRules, DeathRule } from './types'\n\ntype BodyChange = Extract<DestructionEvent, { type: 'body' }>['change']\ntype KillCause = 'head' | 'vitality' | 'bleed' | 'explosion'\ntype EventDraft = DestructionEvent extends infer E ? (E extends DestructionEvent ? Omit<E, 'object' | 'time'> : never) : never\n\nexport type BleedParams = { readonly segment: SegmentState; readonly rate: number; readonly duration: number; readonly spurt: boolean; readonly point?: Vec3; readonly direction?: Vec3 }\n\n/** How severing treats what hangs below: the Arsenal only detaches it, the Elenco also zeroes it and marks it cut. */\nexport type SeverBelow = 'detach' | 'zero'\n\n/** Every change a damage rule can make to a body, each emitting its events. The rules (kit, arsenal, elenco, regions) only decide. */\nexport type BodyOps = {\n readonly body: BodyState\n readonly spec: ResolvedCharacterSpec\n readonly rules: DamageRules\n readonly random: () => number\n readonly events: DestructionEvent[]\n emit(event: EventDraft): void\n pointOf(id: SegmentId): Vec3\n change(change: BodyChange, part?: SegmentId, extra?: { cause?: KillCause; below?: string[] }): void\n damage(segment: SegmentState, amount: number, damageType: DamageType): void\n wound(segment: SegmentState): void\n breakBone(segment: SegmentState): void\n sever(segment: SegmentState, below?: SeverBelow): void\n destroy(segment: SegmentState): void\n kill(cause: KillCause): void\n limp(side: SegmentSide): void\n crawl(): void\n /** A heavy hit staggers the body for the spec's `stunSeconds`. */\n stun(): void\n bleed(params: BleedParams): void\n}\n\nexport type CreateBodyOpsParams = {\n readonly body: BodyState\n readonly spec: ResolvedCharacterSpec\n readonly rules: DamageRules\n readonly random: () => number\n readonly time: number\n readonly source?: string\n readonly pointOf: (id: SegmentId) => Vec3\n readonly bleeders: Bleeder[]\n}\n\nconst killAllowed = (rule: DeathRule, cause: KillCause): boolean => rule === 'vitality-or-head' || cause === 'head' || cause === 'explosion'\n\nexport const createBodyOps = ({ body, spec, rules, random, time, source, pointOf, bleeders }: CreateBodyOpsParams): BodyOps => {\n const events: DestructionEvent[] = []\n const emit = (event: EventDraft): void => void events.push({ ...event, object: spec.id, time, ...(source !== undefined ? { source } : {}) } as DestructionEvent)\n const change: BodyOps['change'] = (kind, part, extra) => emit({ type: 'body', change: kind, ...(part ? { part } : {}), ...extra })\n const detachBelow = (segment: SegmentState, below: SeverBelow): SegmentId[] => {\n const fallen = segmentsBelow(segment.id).filter((id) => segmentOf(body, id).attached)\n segment.attached = false\n for (const id of fallen) {\n const part = segmentOf(body, id)\n part.attached = false\n if (below === 'zero') Object.assign(part, { hp: 0, status: 'severed' })\n }\n return fallen\n }\n const ops: BodyOps = {\n body,\n spec,\n rules,\n random,\n events,\n emit,\n pointOf,\n change,\n damage: (segment, amount, damageType) => emit({ type: 'damage', part: segment.id, amount, hp: Math.max(0, segment.hp), damageType }),\n wound(segment) {\n if (segment.status === 'ok') segment.status = 'wounded'\n change('wound', segment.id)\n },\n breakBone(segment) {\n segment.status = 'broken'\n change('broken', segment.id)\n },\n sever(segment, below = 'detach') {\n if (!segment.attached) return\n const fallen = detachBelow(segment, below)\n segment.status = 'severed'\n body.pieces.push([segment.id, ...fallen])\n const parent = segmentNode(segment.id).parent\n change('severed', segment.id, { below: fallen })\n if (parent) emit({ type: 'detach', joint: `${parent}~${segment.id}`, parts: [parent, segment.id], by: 'break', groups: [[segment.id, ...fallen]] })\n },\n destroy(segment) {\n if (!segment.attached) return\n const fallen = detachBelow(segment, 'detach')\n segment.status = 'destroyed'\n if (fallen.length > 0) body.pieces.push(fallen)\n change('destroyed', segment.id, { below: fallen })\n emit({ type: 'fracture', part: segment.id, style: 'tear', fragments: [], point: pointOf(segment.id) })\n },\n kill(cause) {\n if (!body.alive || !killAllowed(rules.deathRule, cause)) return\n body.alive = false\n change('killed', undefined, { cause })\n },\n limp(side) {\n if (body.limping.includes(side)) return\n body.limping.push(side)\n change('limp')\n },\n crawl() {\n if (body.crawl) return\n body.crawl = true\n change('crawl')\n },\n stun() {\n body.stunSeconds = spec.stunSeconds\n change('stunned')\n },\n bleed({ segment, rate, duration, spurt, point, direction }) {\n const scaled = rate * spec.bloodFactor\n bleeders.push({ part: segment.id, rate: scaled, duration, spurt, age: 0, reported: 0 })\n emit({ type: 'leak', part: segment.id, fluid: 'blood', point: point ?? pointOf(segment.id), direction: direction ?? [0, -1, 0], rate: scaled * BLOOD_LITERS_PER_DROP, pressurized: spurt })\n },\n }\n return ops\n}\n","{\n \"id\": \"physical\",\n \"tissuePerCentimetre\": {\n \"flesh\": 0.25,\n \"bone\": 1\n },\n \"torsoPath\": {\n \"fleshCentimetres\": 22,\n \"boneCentimetres\": 2\n },\n \"regionFactor\": {\n \"head\": 0.7,\n \"limb\": 0.5,\n \"torso\": 1\n },\n \"bruteTorsoFactor\": 2,\n \"energyKept\": \"P / (P + R)\",\n \"points\": {\n \"coefficient\": 3.5,\n \"exponent\": 0.37\n },\n \"tolerance\": {\n \"bodies\": 0,\n \"energyKept\": 0.05\n },\n \"calibration\": [\n {\n \"caliber\": \"9x19\",\n \"force\": 7.67,\n \"bodies\": 2,\n \"energyKeptFirstBody\": 0.51,\n \"expectedBodies\": 2,\n \"bestiaryEnergyKept\": 0.5\n },\n {\n \"caliber\": \"5_56x45\",\n \"force\": 16.56,\n \"bodies\": 3,\n \"energyKeptFirstBody\": 0.69,\n \"expectedBodies\": 3,\n \"bestiaryEnergyKept\": 0.65\n },\n {\n \"caliber\": \"7_62x51\",\n \"force\": 26.67,\n \"bodies\": 4,\n \"energyKeptFirstBody\": 0.78,\n \"expectedBodies\": 4,\n \"bestiaryEnergyKept\": 0.75\n },\n {\n \"caliber\": \"7_62x39\",\n \"force\": 18.52,\n \"bodies\": 3,\n \"energyKeptFirstBody\": 0.71,\n \"expectedBodies\": 3\n },\n {\n \"caliber\": \"12ga_00buck\",\n \"force\": 4.35,\n \"bodies\": 1,\n \"energyKeptFirstBody\": 0.37,\n \"expectedBodies\": 1\n }\n ],\n \"torsoResistance\": 7.5\n}\n","import type { SegmentKind } from '@adatechnology/game-contracts'\n\nimport { SEGMENT_NUMBERS } from '../body/segment-tree'\nimport segments from '../data/segments.json'\nimport physical from '../presets/physical.json'\nimport teamGame from '../presets/team-game.json'\nimport type { BallisticClass, CaliberEntry, DamageRules, ProtectionLayer } from './types'\n\nconst { severity } = segments\n\n/** The kit's rules: Arsenal numbers per segment (A4), the design's severity, the game's head rule, death by vitality or head. */\nexport const DEFAULT_DAMAGE_RULES: DamageRules = {\n deathRule: 'vitality-or-head',\n segmentRule: 'kit',\n severity: { ...severity, stunAtPoints: 35, limbVitalityShare: 0.3, regionLimbVitalityShare: 0.5 },\n blast: { minimumPoints: 8, headDestroyPoints: 40, bigPoints: 120 },\n defaultCut: segments.defaultCut,\n points: physical.points,\n spread: 0,\n segments: SEGMENT_NUMBERS,\n burnPointsPerSecond: 3,\n}\n\n/** The Galeria 3D do Arsenal, replayed: its `damage`, `sever`, `explodeSeg`, `splitTorso`, `legLost` and `grenadeAt`. */\nexport const ARSENAL_RULES: DamageRules = { ...DEFAULT_DAMAGE_RULES, segmentRule: 'arsenal' }\n\nconst ELENCO_HIT_POINTS = segments.elenco.segments as Partial<Record<SegmentKind, { readonly hp: number }>>\n\n/** The Elenco, replayed: its own hit points, no multiplier, ±15 % per blow and its cut rule (`hit`, `sever`, `breakBone`); a torso at 0 kills (a human). */\nexport const ELENCO_RULES: DamageRules = {\n ...DEFAULT_DAMAGE_RULES,\n segmentRule: 'elenco',\n spread: 0.15,\n segments: Object.fromEntries(\n Object.entries(SEGMENT_NUMBERS).map(([kind, numbers]) => [kind, { ...numbers, multiplier: 1, hitPoints: ELENCO_HIT_POINTS[kind as SegmentKind]?.hp ?? numbers.hitPoints }]),\n ) as DamageRules['segments'],\n}\n\nexport const DAMAGE_PRESETS = { kit: DEFAULT_DAMAGE_RULES, arsenal: ARSENAL_RULES, elenco: ELENCO_RULES } as const\n\n/** The protection presets that reproduce the game's `ROUPAS` (tools/characters-catalog/decisions.json `protectionPresets`). */\nexport const PROTECTION_PRESETS: readonly ProtectionLayer[] = [\n { id: 'vest_police', slots: ['torso'], ballistic: { resistance: 14, blunt: 0.3, pass: 0.8 } },\n { id: 'vest_military', slots: ['torso'], ballistic: { resistance: 28, blunt: 0.5 } },\n { id: 'helmet_combat', slots: ['head'], ballistic: { resistance: 9, blunt: 0, pass: 1, consumable: true } },\n { id: 'turnout_gear', slots: ['torso', 'arms', 'legs'], fire: 0.25, limbs: 0.8 },\n]\n\nconst CLASS_OF: Readonly<Record<string, BallisticClass>> = { pistol: 'pistol', rifle: 'rifle' }\n\n/** The game's calibre table (`CALIBRES`) under the kit's calibre ids, for the `team-game` model. */\nexport const TEAM_GAME_CALIBERS: readonly CaliberEntry[] = Object.entries(teamGame.calibers).map(([id, entry]) => ({\n id,\n points: entry.points,\n penetration: entry.penetration,\n class: CLASS_OF[entry.class] ?? 'pistol',\n skullRange: entry.skullRange,\n pellets: 'pellets' in entry ? entry.pellets : 1,\n effectiveRangeMetres: entry.effectiveRangeMetres,\n}))\n\n/** The game's calibre keys (`9x19`, `12ga`, `762x39`, `308`) to the kit's calibre ids. */\nexport const TEAM_GAME_CALIBER_KEYS: Readonly<Record<string, string>> = Object.fromEntries(Object.entries(teamGame.calibers).map(([id, entry]) => [entry.gameKey, id]))\n\nexport const TEAM_GAME_RULES = { regionCost: teamGame.regionCost, damageKeptPerBody: teamGame.damageKeptPerBody, falloff: teamGame.falloff } as const\n\nexport const PHYSICAL_RULES = physical\n","import type { BodyRegion, SegmentKind } from '@adatechnology/game-contracts'\n\nimport { PHYSICAL_RULES, TEAM_GAME_RULES } from './defaults'\nimport type { PenetrationModel } from './types'\n\n/** P = √(E·m/A) against the resistance of the path; a protection layer stops a projectile whose force is not above its resistance. */\nexport const PHYSICAL_PENETRATION: PenetrationModel = {\n id: 'physical',\n stops: (layer, projectile) => projectile.force <= (layer.ballistic?.resistance ?? 0),\n piercesSkull: (projectile, headResistance) => projectile.force > headResistance,\n}\n\n/** The game's rule: pistol-class rounds are stopped by a vest or a helmet; the skull is pierced within the calibre's `cranio` range. */\nexport const TEAM_GAME_PENETRATION: PenetrationModel = {\n id: 'team-game',\n stops: (_layer, projectile) => projectile.class === 'pistol',\n piercesSkull: (projectile) => projectile.skullRange === 1 || projectile.distance <= projectile.skullRange,\n}\n\nexport const PENETRATION_MODELS = { physical: PHYSICAL_PENETRATION, 'team-game': TEAM_GAME_PENETRATION } as const\n\nconst { tissuePerCentimetre, torsoPath, regionFactor } = PHYSICAL_RULES\n\n/** Resistance of a torso path: flesh 22 cm × 0.25 + bone 2 cm × 1.0 = 7.5. */\nexport const TORSO_RESISTANCE = torsoPath.fleshCentimetres * tissuePerCentimetre.flesh + torsoPath.boneCentimetres * tissuePerCentimetre.bone\n\nconst HEAD_KINDS: ReadonlySet<SegmentKind> = new Set(['head', 'jaw', 'neck'])\nconst TORSO_KINDS: ReadonlySet<SegmentKind> = new Set(['torso', 'pelvis'])\n\nexport type ResistanceParams = { readonly kind: SegmentKind; readonly bodyCount: number; readonly protection: number }\n\n/** R of the path through a segment: torso 7.5 (× the body count of a brute), head 0.7×, limbs 0.5×, plus the protection worn over it. */\nexport const segmentResistance = ({ kind, bodyCount, protection }: ResistanceParams): number => {\n if (TORSO_KINDS.has(kind)) return TORSO_RESISTANCE * regionFactor.torso * bodyCount + protection\n if (HEAD_KINDS.has(kind)) return TORSO_RESISTANCE * regionFactor.head + protection\n return TORSO_RESISTANCE * regionFactor.limb + protection\n}\n\n/** Share of the energy a projectile of force `force` keeps after a path of resistance `resistance`: P/(P+R). */\nexport const energyKept = (force: number, resistance: number): number => (force > 0 ? force / (force + resistance) : 0)\n\n/** Penetration points a region costs in the game (`custo`): head 0.7, torso 1 (a brute 2), limb 0.5. */\nexport const teamGameCost = (region: BodyRegion, bodyCount: number): number => {\n const cost = TEAM_GAME_RULES.regionCost\n if (region === 'head') return cost.head\n if (region === 'torso') return bodyCount > 1 ? cost.bruteTorso : cost.torso\n return cost.limb\n}\n\n/** The game's falloff: full damage up to the effective range, then linear down to half at twice the range, never below half. */\nexport const teamGameFalloff = (distance: number, range: number): number => {\n const floor = TEAM_GAME_RULES.falloff.atTwiceRange\n return distance <= range * TEAM_GAME_RULES.falloff.fullAtRange ? 1 : Math.max(floor, 1 - ((distance - range) / range) * (1 - floor))\n}\n","import type { DamageType, SegmentKind, Vec3 } from '@adatechnology/game-contracts'\n\nimport { segmentNode } from '../../body/segment-tree'\nimport type { ResolvedCharacterSpec } from '../../character'\nimport type { SegmentState } from '../../types'\nimport type { BodyOps } from '../body-ops'\nimport type { PenetrationModel, ProjectileInfo } from '../types'\n\n/** One blow on one segment, after protection: what every segment rule receives. */\nexport type SegmentBlow = {\n readonly segment: SegmentState\n /** Points after protection, before the rule's multipliers and spread. */\n readonly points: number\n readonly cut: number\n readonly damageType: DamageType\n readonly projectile?: ProjectileInfo\n readonly explosive: boolean\n /** A blast strong enough to destroy what it takes to 0 (Arsenal `big`). */\n readonly big: boolean\n /** Where it landed (world): a bullet wound bleeds there; a blast share has none. */\n readonly point?: Vec3\n /** Extra factor on arms and legs (age × protection). */\n readonly limbFactor: number\n readonly model: PenetrationModel\n /** Resistance of the head path (the skull rule of the `physical` model). */\n readonly headResistance: number\n}\n\nexport type RuleResult = { readonly headshot: boolean }\n\nexport type SegmentRule = (ops: BodyOps, blow: SegmentBlow) => RuleResult\n\nexport const NO_HEADSHOT: RuleResult = { headshot: false }\nexport const HEADSHOT: RuleResult = { headshot: true }\n\nconst ARM_KINDS: ReadonlySet<SegmentKind> = new Set(['upperArm', 'forearm', 'hand'])\nconst LEG_KINDS: ReadonlySet<SegmentKind> = new Set(['thigh', 'shin', 'foot'])\n\nexport const isArm = (kind: SegmentKind): boolean => ARM_KINDS.has(kind)\nexport const isLeg = (kind: SegmentKind): boolean => LEG_KINDS.has(kind)\nexport const isLimb = (kind: SegmentKind): boolean => isArm(kind) || isLeg(kind)\n\n/** The body type's multiplier for the group the segment is in (head, torso, arms, legs). */\nexport const typeMultiplier = (spec: ResolvedCharacterSpec, kind: SegmentKind): number => {\n if (isArm(kind)) return spec.multipliers.arms\n if (isLeg(kind)) return spec.multipliers.legs\n if (kind === 'torso' || kind === 'pelvis') return spec.multipliers.torso\n return spec.multipliers.head\n}\n\n/** Points the segment takes: the blow × segment multiplier × body type × (on a limb) age and protection. */\nexport const segmentDamage = (ops: BodyOps, blow: SegmentBlow, points: number): number => {\n const { kind } = blow.segment\n return points * ops.rules.segments[kind].multiplier * typeMultiplier(ops.spec, kind) * (isLimb(kind) ? blow.limbFactor : 1)\n}\n\n/** The stump a lost segment leaves bleeds hard (×1.5 at the neck and head) for 45 s, spurting (Arsenal `stumpAt`). */\nexport const bleedStump = (ops: BodyOps, segment: SegmentState): void => {\n const bleed = ops.rules.segments[segment.kind].bleed\n const parent = segmentNode(segment.id).parent\n const stump = parent ? (ops.body.segments.find((candidate) => candidate.id === parent) ?? segment) : segment\n ops.bleed({ segment: stump, rate: bleed * (segment.kind === 'neck' || segment.kind === 'head' ? 1.5 : 1), duration: 45, spurt: true })\n}\n\n/** The piece that flies off bleeds 35 % of the rate for 15 s (Arsenal `sever`). */\nexport const bleedPiece = (ops: BodyOps, segment: SegmentState): void => ops.bleed({ segment, rate: ops.rules.segments[segment.kind].bleed * 0.35, duration: 15, spurt: true })\n\n/** A bullet wound bleeds 30 % of the segment's rate for 10 s, without spurting (Arsenal `damage` with a point). */\nexport const bleedWound = (ops: BodyOps, segment: SegmentState, point: Vec3): void =>\n ops.bleed({ segment, rate: ops.rules.segments[segment.kind].bleed * 0.3, duration: 10, spurt: false, point })\n\n/** Cut off at the joint, with its two bleeders. */\nexport const severWithBleeding = (ops: BodyOps, segment: SegmentState): void => {\n if (!segment.attached) return\n bleedStump(ops, segment)\n ops.sever(segment)\n bleedPiece(ops, segment)\n}\n\n/** Blown to pieces: only the stump bleeds. */\nexport const destroyWithBleeding = (ops: BodyOps, segment: SegmentState): void => {\n if (!segment.attached) return\n bleedStump(ops, segment)\n ops.destroy(segment)\n}\n","import { MISSING_BITS } from '@adatechnology/game-contracts'\nimport type { BodyRegion, DamageType } from '@adatechnology/game-contracts'\n\nimport { segmentOf } from '../../body/body-state'\nimport { REGION_HIT_POINTS, REGION_SEGMENTS } from '../../body/regions'\nimport type { LimbRegion } from '../../body/regions'\nimport type { BodyOps } from '../body-ops'\nimport { spreadPoints } from '../points'\nimport type { ProtectionOutcome } from '../protection'\nimport type { PenetrationModel, ProjectileInfo } from '../types'\nimport { HEADSHOT, NO_HEADSHOT } from './blow'\nimport type { RuleResult } from './blow'\n\n/** One blow on one crowd region. `points` are the blow's own (the game stuns on them); the torso applies the vest share itself. */\nexport type RegionBlow = {\n readonly region: BodyRegion\n readonly points: number\n readonly cut: number\n readonly damageType: DamageType\n readonly projectile?: ProjectileInfo\n readonly protection: ProtectionOutcome\n readonly model: PenetrationModel\n readonly headResistance: number\n}\n\nconst LIMB_BITS: Readonly<Record<Exclude<LimbRegion, 'head'>, { readonly severed: number; readonly broken: number }>> = {\n armL: { severed: MISSING_BITS.armL, broken: MISSING_BITS.armLBroken },\n armR: { severed: MISSING_BITS.armR, broken: MISSING_BITS.armRBroken },\n legL: { severed: MISSING_BITS.legL, broken: MISSING_BITS.legLBroken },\n legR: { severed: MISSING_BITS.legR, broken: MISSING_BITS.legRBroken },\n}\n\nconst rootOf = (ops: BodyOps, region: BodyRegion) => segmentOf(ops.body, REGION_SEGMENTS[region][0] as Parameters<typeof segmentOf>[1])\n\nconst hitHead = (ops: BodyOps, blow: RegionBlow, points: number): RuleResult => {\n const { body, rules } = ops\n const rule = rules.severity\n const multiplier = rules.segments.head.multiplier\n const { projectile } = blow\n const lethal = projectile ? blow.model.piercesSkull(projectile, blow.headResistance) && points >= rule.headKillDamage : points * multiplier >= body.regions.head\n if (lethal) {\n const shotgunClose = projectile !== undefined && projectile.pellets > 1 && projectile.distance < rule.headBitShotgunMetres\n if (points > rule.headBitDamage || shotgunClose) {\n body.missing |= MISSING_BITS.head\n ops.destroy(segmentOf(body, 'head'))\n }\n return HEADSHOT\n }\n body.vitality -= points * multiplier\n body.regions.head -= points\n ops.damage(segmentOf(body, 'head'), points * multiplier, blow.damageType)\n if (points > rule.jawDamage && ops.random() < rule.jawChance && (body.missing & MISSING_BITS.jaw) === 0) {\n body.missing |= MISSING_BITS.jaw\n ops.sever(segmentOf(body, 'jaw'))\n }\n return NO_HEADSHOT\n}\n\nconst hitLimb = (ops: BodyOps, blow: RegionBlow, region: Exclude<LimbRegion, 'head'>, points: number): void => {\n const { body, spec, rules } = ops\n const leg = region === 'legL' || region === 'legR'\n const factor = (leg ? spec.multipliers.legs : spec.multipliers.arms) * spec.limbFactor * blow.protection.limbs\n const amount = points * factor\n body.regions[region] -= amount\n body.vitality -= amount * rules.severity.regionLimbVitalityShare\n const root = rootOf(ops, region)\n ops.damage(root, amount, blow.damageType)\n const max = REGION_HIT_POINTS[region]\n if (leg && body.regions[region] <= max * rules.severity.limpAtHpFraction) ops.limp(region === 'legL' ? 'L' : 'R')\n if (body.regions[region] > 0) return\n const severs = blow.cut >= rules.severity.severAtCut || amount > max * rules.severity.severAtDamageFraction\n const bit = severs ? LIMB_BITS[region].severed : LIMB_BITS[region].broken\n const isNew = (body.missing & bit) === 0\n body.missing |= bit\n if (leg) ops.crawl()\n if (!isNew) return\n if (severs) ops.sever(root)\n else ops.breakBone(root)\n}\n\n/** The game's `zDamage` (G 67011–67045): the crowd model of 6 regions, the bitmask, the helmet, the vest, limp, crawl and the jaw. */\nexport const regionRule = (ops: BodyOps, blow: RegionBlow): RuleResult => {\n const { body, rules } = ops\n const points = spreadPoints(blow.points, rules.spread, ops.random)\n let result = NO_HEADSHOT\n if (blow.region === 'head') result = hitHead(ops, blow, points)\n else if (blow.region === 'torso') {\n const amount = points * ops.spec.multipliers.torso * blow.protection.ballistic\n body.vitality -= amount\n ops.damage(segmentOf(body, 'torso'), amount, blow.damageType)\n } else hitLimb(ops, blow, blow.region, points)\n if (result.headshot) ops.kill('head')\n else if (body.vitality <= 0) ops.kill('vitality')\n if (!body.alive || result.headshot || body.vitality <= 0) return result\n if (points >= rules.severity.stunAtPoints) ops.stun()\n return result\n}\n","import type { DamageType } from '@adatechnology/game-contracts'\n\nimport type { BallisticClass, BodyHit, CaliberEntry, DamageRules, ProjectileInfo } from './types'\n\n/** Deterministic mulberry32 stream in [0, 1). */\nexport const createRng = (seed: number): (() => number) => {\n let state = seed >>> 0\n return () => {\n state = (state + 0x6d2b79f5) >>> 0\n let mixed = Math.imul(state ^ (state >>> 15), state | 1)\n mixed ^= mixed + Math.imul(mixed ^ (mixed >>> 7), mixed | 61)\n return ((mixed ^ (mixed >>> 14)) >>> 0) / 4294967296\n }\n}\n\n/** Damage points of a blow from its energy in joules: `coefficient · E^exponent` (9×19 → 35, 7.62×39 → 59, .308 → 71.7). */\nexport const pointsFromEnergy = (energy: number, rules: Pick<DamageRules, 'points'>): number => (energy > 0 ? rules.points.coefficient * energy ** rules.points.exponent : 0)\n\n/** The caller's points, else the calibre table's, else the energy formula. */\nexport const resolvePoints = (hit: BodyHit, caliber: CaliberEntry | undefined, rules: Pick<DamageRules, 'points'>): number => hit.points ?? caliber?.points ?? pointsFromEnergy(hit.energy ?? 0, rules)\n\n/** One draw of ±`spread` on the points (none when the spread is 0, so the stream is not touched). */\nexport const spreadPoints = (points: number, spread: number, random: () => number): number => (spread > 0 ? points * (1 - spread + random() * 2 * spread) : points)\n\nconst DEFAULT_PROJECTILE_GRAMS = 8\nconst RIFLE_JOULES = 1000\n\n/** P = √(E·m/A): E in joules, m in grams, A the cross-section in mm². */\nexport const penetrationForce = (energy: number, grams: number, diameterMm: number): number => {\n const area = (Math.PI * diameterMm ** 2) / 4\n return area > 0 && energy > 0 ? Math.sqrt((energy * grams) / area) : 0\n}\n\n/** What a ballistic hit is (force, class, skull range, pellets, distance), from the hit and the calibre table. */\nexport const projectileOf = (hit: BodyHit, caliber: CaliberEntry | undefined): ProjectileInfo => {\n const pellets = hit.pellets ?? caliber?.pellets ?? 1\n const energy = hit.energy ?? 0\n const fallback: BallisticClass = energy > RIFLE_JOULES ? 'rifle' : 'pistol'\n return {\n force: penetrationForce(energy, hit.mass ?? DEFAULT_PROJECTILE_GRAMS, hit.caliber ?? 9),\n class: caliber?.class ?? fallback,\n skullRange: caliber?.skullRange ?? 1,\n pellets,\n distance: hit.distance ?? 0,\n }\n}\n\n/** `hit.cut`, else the default of its damage type (a bullet by class: pistol 0.15, buckshot 0.75, rifle 0.45). */\nexport const cutOf = (hit: BodyHit, projectile: ProjectileInfo | undefined, rules: Pick<DamageRules, 'defaultCut'>): number => {\n if (hit.cut !== undefined) return hit.cut\n const type: DamageType = hit.type\n if (type === 'ballistic' && projectile) return rules.defaultCut.ballistic[projectile.pellets > 1 ? 'buckshot' : projectile.class]\n if (type === 'slash' || type === 'blunt' || type === 'explosive') return rules.defaultCut[type]\n return 0\n}\n","import type { Vec3 } from '@adatechnology/game-contracts'\n\nimport { REGION_SEGMENTS, BODY_REGIONS } from '../body/regions'\nimport { segmentNode } from '../body/segment-tree'\nimport type { SegmentId } from '../body/segment-tree'\nimport { distance } from '../body/transform'\nimport type { BodyOps } from './body-ops'\nimport { HEADSHOT, NO_HEADSHOT, destroyWithBleeding } from './rules/blow'\nimport type { RuleResult, SegmentBlow, SegmentRule } from './rules/blow'\nimport { regionRule } from './rules/regions'\nimport type { RegionBlow } from './rules/regions'\n\nexport type BlastParams = {\n readonly ops: BodyOps\n /** Centre of the blast in the body's local space. */\n readonly center: Vec3\n readonly points: number\n readonly radius: number\n /** A joint position in local space. */\n readonly jointOf: (id: SegmentId) => Vec3\n}\n\n/** The share of a blast each target takes: points × (1 − distance/radius), kept above the minimum, strongest first (Arsenal `grenadeAt`). */\nconst shares = <TTarget>(params: BlastParams, targets: readonly TTarget[], pivot: (target: TTarget) => SegmentId): { target: TTarget; points: number }[] =>\n targets\n .map((target) => ({ target, points: params.points * Math.max(0, 1 - distance(params.jointOf(pivot(target)), params.center) / params.radius) }))\n .filter((share) => share.points > params.ops.rules.blast.minimumPoints)\n .sort((a, b) => b.points - a.points)\n\nexport type SegmentBlastParams = BlastParams & { readonly rule: SegmentRule; readonly blow: Omit<SegmentBlow, 'segment' | 'points' | 'big' | 'explosive' | 'point'> }\n\n/** A blast on the 17 segments: a strong share on the head blows it off; every other share goes through the segment rule as an explosive blow. */\nexport const segmentBlast = (params: SegmentBlastParams): RuleResult => {\n const { ops, rule, blow } = params\n const { blast, segments } = ops.rules\n let result = NO_HEADSHOT\n for (const { target, points } of shares(params, ops.body.segments.filter((segment) => segment.attached), (segment) => segment.id)) {\n if (!target.attached) continue\n if (target.kind === 'head' && points > blast.headDestroyPoints) {\n destroyWithBleeding(ops, target)\n ops.kill('explosion')\n result = HEADSHOT\n continue\n }\n rule(ops, { ...blow, segment: target, points: points / segments[target.kind].multiplier, big: points > blast.bigPoints, explosive: true })\n }\n return result\n}\n\nexport type RegionBlastParams = BlastParams & { readonly blow: Omit<RegionBlow, 'region' | 'points'> }\n\n/** A blast on the 6 crowd regions, each measured at the joint of the segment that names it. */\nexport const regionBlast = (params: RegionBlastParams): RuleResult => {\n let result = NO_HEADSHOT\n const pivot = (region: (typeof BODY_REGIONS)[number]): SegmentId => segmentNode(REGION_SEGMENTS[region][0] as SegmentId).id\n for (const { target, points } of shares(params, BODY_REGIONS, pivot)) {\n if (regionRule(params.ops, { ...params.blow, region: target, points }).headshot) result = HEADSHOT\n }\n return result\n}\n","import type { BodySlot } from '@adatechnology/game-contracts'\n\nimport type { PenetrationModel, ProjectileInfo, ProtectionLayer } from './types'\n\n/** The layered protection of T3: `1 − Π(1 − value·condition)`, at most `cap`. */\nexport const LAYERED_PROTECTION_CAP = 0.9\n\nexport type LayeredProtectionParams = {\n readonly layers: readonly ProtectionLayer[]\n readonly attack: 'bite' | 'scratch'\n /** 0..1 condition per layer id (worn, torn); 1 by default. */\n readonly conditions?: Readonly<Record<string, number>>\n}\n\nexport const layeredProtection = ({ layers, attack, conditions }: LayeredProtectionParams): number => {\n const through = layers.reduce((left, layer) => left * (1 - (layer[attack] ?? 0) * (conditions?.[layer.id] ?? 1)), 1)\n return Math.min(LAYERED_PROTECTION_CAP, 1 - through)\n}\n\n/** The layers worn that cover any of `slots` and are not used up. */\nexport const layersOn = (worn: readonly ProtectionLayer[], slots: readonly BodySlot[], consumed: ReadonlySet<string>): ProtectionLayer[] =>\n worn.filter((layer) => !consumed.has(layer.id) && layer.slots.some((slot) => slots.includes(slot)))\n\n/** What the layers over a segment do to one blow. */\nexport type ProtectionOutcome = {\n /** A consumable layer took the whole projectile (a helmet): no damage, and the layer is used up. */\n readonly absorbedBy?: string\n /** Share of the points that gets through the ballistic layers. */\n readonly ballistic: number\n /** Penetration resistance the layers add (the `physical` model). */\n readonly resistance: number\n /** Factor on limb damage (a turnout coat). */\n readonly limbs: number\n /** Factor on fire damage. */\n readonly fire: number\n}\n\nexport type ProtectParams = {\n readonly layers: readonly ProtectionLayer[]\n readonly projectile?: ProjectileInfo\n readonly model: PenetrationModel\n}\n\n/** A stopped projectile does the layer's `blunt` share; one that goes through, `pass` (default `blunt`). Non-projectiles ignore ballistic layers. */\nexport const protect = ({ layers, projectile, model }: ProtectParams): ProtectionOutcome => {\n let ballistic = 1\n let resistance = 0\n for (const layer of layers) {\n const armour = layer.ballistic\n if (!armour || !projectile) continue\n const stops = model.stops(layer, projectile)\n if (stops && armour.consumable) return { absorbedBy: layer.id, ballistic: 0, resistance: armour.resistance, limbs: 1, fire: 1 }\n ballistic *= stops ? armour.blunt : (armour.pass ?? armour.blunt)\n resistance += armour.resistance\n }\n const limbs = layers.reduce((factor, layer) => factor * (layer.limbs ?? 1), 1)\n const fire = layers.reduce((factor, layer) => factor * (layer.fire ?? 1), 1)\n return { ballistic, resistance, limbs, fire }\n}\n","import type { BodyRegion, DestructibleSpec, Vec3 } from '@adatechnology/game-contracts'\n\nimport type { BodyState } from '../body/body-state'\nimport { isBodyRegion, REGION_SEGMENTS } from '../body/regions'\nimport { isSegmentId } from '../body/segment-tree'\nimport type { SegmentId } from '../body/segment-tree'\nimport { distance } from '../body/transform'\n\nconst radiusOf = (part: DestructibleSpec['parts'][number]): number => (part.shape.kind === 'box' ? Math.min(...part.shape.size) / 2 : part.shape.radius)\n\n/**\n * The segment a hit lands on: `hit.part` when the caller resolved it (a segment id, or a region id for its first segment), else the attached\n * part whose surface is nearest to the local point.\n */\nexport const resolveSegment = (body: BodyState, spec: DestructibleSpec, part: string | undefined, localPoint: Vec3): SegmentId => {\n if (part !== undefined && isSegmentId(part)) return part\n if (part !== undefined && isBodyRegion(part)) return REGION_SEGMENTS[part][0] as SegmentId\n let best: SegmentId = 'torso'\n let bestGap = Infinity\n for (const candidate of spec.parts) {\n const segment = body.segments.find((entry) => entry.id === candidate.id)\n if (!segment?.attached) continue\n const gap = distance(candidate.position, localPoint) - radiusOf(candidate)\n if (gap < bestGap) [best, bestGap] = [segment.id, gap]\n }\n return best\n}\n\nexport const regionOfSegment = (body: BodyState, id: SegmentId): BodyRegion => body.segments.find((segment) => segment.id === id)?.region ?? 'torso'\n","import { segmentOf } from '../../body/body-state'\nimport type { SegmentState } from '../../types'\nimport type { BodyOps } from '../body-ops'\nimport { HEADSHOT, NO_HEADSHOT, bleedWound, destroyWithBleeding, segmentDamage, severWithBleeding } from './blow'\nimport type { SegmentBlow, SegmentRule } from './blow'\n\n/** A blow of at least this many points blows the head off (Arsenal `damage`: `dmg >= 30`). */\nconst HEAD_BLOW_POINTS = 30\nconst LIMB_VITALITY_SHARE = 0.3\n\nconst split = (ops: BodyOps): void => {\n const torso = segmentOf(ops.body, 'torso')\n if (!torso.attached) return\n severWithBleeding(ops, torso)\n ops.change('split', 'torso')\n ops.kill('vitality')\n}\n\nconst loseLimb = (ops: BodyOps, segment: SegmentState, blow: SegmentBlow): void => {\n if (blow.big || -segment.hp > segment.max) destroyWithBleeding(ops, segment)\n else severWithBleeding(ops, segment)\n const { body } = ops\n if (segment.kind === 'thigh' || segment.kind === 'shin') {\n if (body.alive) ops.crawl()\n } else if (segment.kind === 'foot' && body.alive && !body.crawl && body.limping.length === 0 && segment.side) ops.limp(segment.side)\n}\n\n/** The Galeria 3D do Arsenal's `damage`: every number and branch of the page, in its order. */\nexport const arsenalRule: SegmentRule = (ops, blow) => {\n const { segment } = blow\n if (!segment.attached) return NO_HEADSHOT\n const amount = segmentDamage(ops, blow, blow.points)\n if (blow.point) bleedWound(ops, segment, blow.point)\n segment.hp -= amount\n ops.damage(segment, amount, blow.damageType)\n let result = NO_HEADSHOT\n if (segment.kind === 'head') {\n if (blow.points >= HEAD_BLOW_POINTS || segment.hp <= 0) {\n destroyWithBleeding(ops, segment)\n ops.kill('head')\n result = HEADSHOT\n } else ops.wound(segment)\n } else if (segment.kind === 'jaw') {\n if (segment.hp <= 0) severWithBleeding(ops, segment)\n } else if (segment.kind === 'neck') {\n if (segment.hp <= 0) {\n severWithBleeding(ops, segment)\n ops.kill('head')\n }\n } else if (segment.kind === 'torso' || segment.kind === 'pelvis') {\n ops.body.vitality -= amount\n if (blow.points >= ops.rules.severity.splitAtDamage || segment.hp <= 0) split(ops)\n } else {\n ops.body.vitality -= amount * LIMB_VITALITY_SHARE\n if (segment.hp <= 0) loseLimb(ops, segment, blow)\n }\n if (ops.body.alive && ops.body.vitality <= 0) ops.kill('vitality')\n return result\n}\n","import type { SegmentKind } from '@adatechnology/game-contracts'\n\nimport { spreadPoints } from '../points'\nimport { HEADSHOT, NO_HEADSHOT, isLeg, segmentDamage } from './blow'\nimport type { SegmentRule } from './blow'\n\n/** A head at 0 is cut off by an edge of at least this `cut` or a blow of at least this many points (Elenco `hit`). */\nconst HEAD_SEVER_CUT = 0.7\nconst HEAD_SEVER_POINTS = 90\n/** The segments that hang from a joint of their own in the Elenco (`s.node`): they are cut or break at it. */\nconst JOINTED: ReadonlySet<SegmentKind> = new Set(['head', 'upperArm', 'forearm', 'hand', 'thigh', 'shin', 'foot'])\n\n/** The Elenco's `hit`, `sever` and `breakBone`: one ±15 % draw per blow, cut at the joint above, broken bones dangle or make the leg limp. */\nexport const elencoRule: SegmentRule = (ops, blow) => {\n const { segment } = blow\n const { body, rules } = ops\n if (!segment.attached || (!body.alive && segment.kind !== 'head')) return NO_HEADSHOT\n const amount = segmentDamage(ops, blow, spreadPoints(blow.points, rules.spread, ops.random))\n segment.hp = Math.max(0, segment.hp - amount)\n ops.damage(segment, amount, blow.damageType)\n if (segment.hp > 0) {\n ops.wound(segment)\n return NO_HEADSHOT\n }\n if (segment.kind === 'head') {\n if (blow.cut >= HEAD_SEVER_CUT || blow.points >= HEAD_SEVER_POINTS) ops.sever(segment, 'zero')\n else ops.breakBone(segment)\n ops.kill('head')\n return HEADSHOT\n }\n if (JOINTED.has(segment.kind)) {\n if (blow.cut >= rules.severity.severAtCut || amount >= segment.max * rules.severity.severAtDamageFraction) {\n ops.sever(segment, 'zero')\n if (isLeg(segment.kind)) ops.crawl()\n return NO_HEADSHOT\n }\n ops.breakBone(segment)\n if (isLeg(segment.kind) && segment.side) {\n ops.limp(segment.side)\n if (body.limping.length === 2) ops.crawl()\n }\n return NO_HEADSHOT\n }\n ops.breakBone(segment)\n if (segment.kind === 'torso') ops.kill('vitality')\n else if (segment.kind === 'pelvis') ops.crawl()\n else if (segment.kind === 'neck') ops.kill('head')\n return NO_HEADSHOT\n}\n","import { segmentOf } from '../../body/body-state'\nimport type { SegmentState } from '../../types'\nimport type { BodyOps } from '../body-ops'\nimport { spreadPoints } from '../points'\nimport { HEADSHOT, NO_HEADSHOT, bleedWound, destroyWithBleeding, isLeg, segmentDamage, severWithBleeding } from './blow'\nimport type { RuleResult, SegmentBlow, SegmentRule } from './blow'\n\ntype Outcome = 'destroyed' | 'severed' | 'broken'\n\n/** At 0: destroyed by a blast or a blow of twice the segment; severed by an edge (`cut` ≥ 0.5) or a blow above 90 % of it; else broken. */\nexport const severityOf = (ops: BodyOps, blow: SegmentBlow, amount: number, max: number): Outcome => {\n const rule = ops.rules.severity\n if (blow.explosive || amount >= max * rule.destroyAtDamageMultiple) return 'destroyed'\n if (blow.cut >= rule.severAtCut || amount > max * rule.severAtDamageFraction) return 'severed'\n return 'broken'\n}\n\nconst lose = (ops: BodyOps, segment: SegmentState, outcome: Outcome): void => {\n if (outcome === 'destroyed') destroyWithBleeding(ops, segment)\n else if (outcome === 'severed') severWithBleeding(ops, segment)\n else ops.breakBone(segment)\n}\n\n/** The game's head rule: a projectile kills when it pierces the skull with enough points, a blow when it takes the head's hit points. */\nconst hitHead = (ops: BodyOps, blow: SegmentBlow, points: number, amount: number, hpBefore: number): RuleResult => {\n const { segment, projectile } = blow\n const rule = ops.rules.severity\n const lethal = projectile ? blow.model.piercesSkull(projectile, blow.headResistance) && points >= rule.headKillDamage : amount >= hpBefore\n if (lethal) {\n const shotgunClose = projectile !== undefined && projectile.pellets > 1 && projectile.distance < rule.headBitShotgunMetres\n if (blow.explosive || points > rule.headBitDamage || shotgunClose) destroyWithBleeding(ops, segment)\n else ops.breakBone(segment)\n ops.kill('head')\n return HEADSHOT\n }\n ops.body.vitality -= amount\n ops.wound(segment)\n if (points > rule.jawDamage && ops.random() < rule.jawChance) severWithBleeding(ops, segmentOf(ops.body, 'jaw'))\n return NO_HEADSHOT\n}\n\nconst hitTorso = (ops: BodyOps, points: number, amount: number, segment: SegmentState): void => {\n ops.body.vitality -= amount\n if (points < ops.rules.severity.splitAtDamage && segment.hp > 0) return ops.wound(segment)\n const torso = segmentOf(ops.body, 'torso')\n if (!torso.attached) return\n severWithBleeding(ops, torso)\n ops.change('split', 'torso')\n if (ops.rules.deathRule === 'head-only') ops.crawl()\n else ops.kill('vitality')\n}\n\nconst hitLimb = (ops: BodyOps, blow: SegmentBlow, amount: number, hpBefore: number): void => {\n const { segment } = blow\n const rule = ops.rules.severity\n ops.body.vitality -= amount * rule.limbVitalityShare\n if (isLeg(segment.kind) && segment.side && segment.hp <= segment.max * rule.limpAtHpFraction) ops.limp(segment.side)\n if (segment.hp > 0 || hpBefore <= 0) return ops.wound(segment)\n const outcome = severityOf(ops, blow, amount, segment.max)\n lose(ops, segment, outcome)\n if (segment.kind === 'thigh' || segment.kind === 'shin') ops.crawl()\n}\n\n/** The kit's rule: Arsenal numbers, the design's severity, the game's head rule, the death rule of the kit. */\nexport const kitRule: SegmentRule = (ops, blow) => {\n const { segment } = blow\n if (!segment.attached) return NO_HEADSHOT\n const points = spreadPoints(blow.points, ops.rules.spread, ops.random)\n const amount = segmentDamage(ops, blow, points)\n if (blow.point && !blow.explosive) bleedWound(ops, segment, blow.point)\n const hpBefore = segment.hp\n segment.hp -= amount\n ops.damage(segment, amount, blow.damageType)\n let result = NO_HEADSHOT\n if (segment.kind === 'head') result = hitHead(ops, blow, points, amount, hpBefore)\n else if (segment.kind === 'torso' || segment.kind === 'pelvis') hitTorso(ops, points, amount, segment)\n else if (segment.kind === 'jaw' || segment.kind === 'neck') {\n if (segment.hp <= 0 && hpBefore > 0) {\n lose(ops, segment, severityOf(ops, blow, amount, segment.max))\n if (segment.kind === 'neck' && !segment.attached) ops.kill('head')\n } else ops.wound(segment)\n } else hitLimb(ops, blow, amount, hpBefore)\n if (ops.body.vitality <= 0) ops.kill('vitality')\n if (ops.body.alive && points >= ops.rules.severity.stunAtPoints) ops.stun()\n return result\n}\n","import type { DestructibleSpec, Vec3 } from '@adatechnology/game-contracts'\n\nimport { segmentOf } from '../body/body-state'\nimport { REGION_SEGMENTS } from '../body/regions'\nimport { segmentNode } from '../body/segment-tree'\nimport type { SegmentId } from '../body/segment-tree'\nimport { regionBlast, segmentBlast } from './blast'\nimport type { BodyOps } from './body-ops'\nimport type { DamageSetup } from './damage-character'\nimport { energyKept, segmentResistance } from './penetration'\nimport { cutOf, pointsFromEnergy, projectileOf, resolvePoints } from './points'\nimport { layersOn, protect } from './protection'\nimport type { ProtectionOutcome } from './protection'\nimport { resolveSegment, regionOfSegment } from './resolve-part'\nimport { arsenalRule } from './rules/arsenal'\nimport type { RuleResult, SegmentRule } from './rules/blow'\nimport { elencoRule } from './rules/elenco'\nimport { kitRule } from './rules/kit'\nimport { regionRule } from './rules/regions'\nimport type { BodyHit, HitReport, ProtectionLayer } from './types'\n\nconst SEGMENT_RULES: Readonly<Record<string, SegmentRule>> = { kit: kitRule, arsenal: arsenalRule, elenco: elencoRule }\nconst HEAD_RESISTANCE = segmentResistance({ kind: 'head', bodyCount: 1, protection: 0 })\nconst NO_PROTECTION: ProtectionOutcome = { ballistic: 1, resistance: 0, limbs: 1, fire: 1 }\nconst ABSORBED_SPARKS = 8\nconst METRES_PER_MM = 0.001\n\nexport type ApplyBlowParams = {\n readonly ops: BodyOps\n readonly hit: BodyHit\n readonly setup: DamageSetup\n readonly worn: readonly ProtectionLayer[]\n readonly localPoint: Vec3\n readonly jointOf: (id: SegmentId) => Vec3\n readonly describe: () => DestructibleSpec\n}\n\nconst report = (ops: BodyOps, fields: Partial<HitReport> & { points: number }, result: RuleResult = { headshot: false }): HitReport => ({\n through: false,\n exitEnergy: 0,\n ...fields,\n killed: !ops.body.alive,\n headshot: result.headshot,\n})\n\n/** Fire and heat: the exposure burns the torso (`burnPointsPerSecond` × seconds), less what the clothing keeps off. */\nconst burn = ({ ops, hit, setup, worn }: ApplyBlowParams): HitReport => {\n const torso = segmentOf(ops.body, 'torso')\n const fire = protect({ layers: layersOn(worn, segmentNode('torso').slots, ops.body.consumed), model: setup.model }).fire\n const points = setup.rules.burnPointsPerSecond * (hit.duration ?? 0) * fire\n ops.body.vitality -= points\n ops.damage(torso, points, hit.type)\n if (ops.body.vitality <= 0) ops.kill('vitality')\n return report(ops, { part: 'torso', points })\n}\n\nconst blast = ({ ops, hit, setup, localPoint, jointOf }: ApplyBlowParams): HitReport => {\n const points = hit.points ?? pointsFromEnergy(hit.energy ?? 0, setup.rules)\n const base = { ops, center: localPoint, points, radius: hit.radius ?? 1, jointOf }\n const common = { cut: hit.cut ?? setup.rules.defaultCut.explosive, damageType: hit.type, model: setup.model, headResistance: HEAD_RESISTANCE }\n const rule = SEGMENT_RULES[setup.rules.segmentRule] ?? kitRule\n const result =\n ops.body.detail === 'regions'\n ? regionBlast({ ...base, blow: { ...common, protection: NO_PROTECTION } })\n : segmentBlast({ ...base, rule, blow: { ...common, limbFactor: ops.spec.limbFactor } })\n return report(ops, { points }, result)\n}\n\nconst DEFAULT_PATH_METRES = 0.2\n\n/** Length of the path through a part (its diameter), for the exit point of a projectile that goes through. */\nconst pathThrough = (spec: DestructibleSpec, id: SegmentId): number => {\n const shape = spec.parts.find((part) => part.id === id)?.shape\n return shape && shape.kind !== 'box' ? 2 * shape.radius : DEFAULT_PATH_METRES\n}\n\nconst exitOf = (hit: BodyHit, depth: number): Vec3 => {\n const [x, y, z] = hit.direction ?? [0, 0, -1]\n return [hit.point[0] + x * depth, hit.point[1] + y * depth, hit.point[2] + z * depth]\n}\n\n/** Bullets, blades and blunt blows: resolve the segment, the protection, the penetration, the points; then the detail's rule decides. */\nconst direct = ({ ops, hit, setup, worn, localPoint, describe }: ApplyBlowParams): HitReport => {\n const { body, spec, rules } = ops\n const caliber = hit.caliberId === undefined ? undefined : setup.calibers.get(hit.caliberId)\n const projectile = hit.type === 'ballistic' ? projectileOf(hit, caliber) : undefined\n const id = resolveSegment(body, describe(), hit.part, localPoint)\n const region = regionOfSegment(body, id)\n const slots = segmentNode(body.detail === 'regions' ? (REGION_SEGMENTS[region][0] as SegmentId) : id).slots\n const protection = protect({ layers: layersOn(worn, slots, body.consumed), model: setup.model, ...(projectile ? { projectile } : {}) })\n if (protection.absorbedBy) {\n body.consumed.add(protection.absorbedBy)\n ops.emit({ type: 'debris', part: id, kind: 'sparks', point: hit.point, normal: [0, 1, 0], count: ABSORBED_SPARKS, speed: 3 })\n return report(ops, { part: id, points: 0, absorbedBy: protection.absorbedBy })\n }\n const rawPoints = resolvePoints(hit, caliber, rules)\n const points = rawPoints * protection.ballistic\n const cut = cutOf(hit, projectile, rules)\n const segment = segmentOf(body, id)\n const resistance = segmentResistance({ kind: segment.kind, bodyCount: spec.bodyCount, protection: protection.resistance })\n const through = setup.model.id === 'physical' && projectile !== undefined && projectile.force > resistance\n const exitEnergy = through && projectile ? (hit.energy ?? 0) * energyKept(projectile.force, resistance) : 0\n if (projectile) {\n const depth = pathThrough(describe(), id)\n ops.emit({ type: 'hole', part: id, hole: { point: localPoint, normal: [0, 0, 1], diameter: (hit.caliber ?? 9) * METRES_PER_MM, through }, worldPoint: hit.point, ...(through ? { exitPoint: exitOf(hit, depth) } : {}) })\n }\n const common = { points, cut, damageType: hit.type, model: setup.model, headResistance: HEAD_RESISTANCE, ...(projectile ? { projectile } : {}) }\n const result =\n body.detail === 'regions'\n ? regionRule(ops, { ...common, points: rawPoints, region, protection })\n : (SEGMENT_RULES[rules.segmentRule] ?? kitRule)(ops, {\n ...common,\n segment,\n explosive: false,\n big: points > rules.blast.bigPoints,\n limbFactor: spec.limbFactor * protection.limbs,\n ...(hit.woundAtPoint === false ? {} : { point: hit.point }),\n })\n return report(ops, { part: id, points, through, exitEnergy }, result)\n}\n\nexport const applyBlow = (params: ApplyBlowParams): HitReport => {\n if (params.hit.type === 'fire' || params.hit.type === 'heat') return burn(params)\n if (params.hit.type === 'explosive') return blast(params)\n return direct(params)\n}\n","import type { DestructibleImpl, DestructionEvent, Hit, Vec3 } from '@adatechnology/game-contracts'\n\nimport type { BodyState } from '../body/body-state'\nimport { segmentNode } from '../body/segment-tree'\nimport type { SegmentId, SegmentSide } from '../body/segment-tree'\nimport { toLocal, toWorld } from '../body/transform'\nimport { characterView } from '../character'\nimport type { Character, CharacterCore } from '../character'\nimport { stepBleeding } from './bleeding'\nimport type { Bleeder } from './bleeding'\nimport { createBodyOps } from './body-ops'\nimport type { BodyOps } from './body-ops'\nimport { segmentResistance } from './penetration'\nimport { applyBlow } from './pipeline'\nimport { createRng } from './points'\nimport { layeredProtection, layersOn } from './protection'\nimport { resolveSegment } from './resolve-part'\nimport type { BodyHit, CaliberEntry, DamageRules, HitReport, PenetrationModel, ProtectionLayer } from './types'\n\n/** A character with the damage model: a `DestructibleImpl` a destruction world can host next to its own objects. */\nexport type DamageCharacter = Character &\n DestructibleImpl & {\n readonly alive: boolean\n /** The sides that limp, in the order they started. */\n readonly limping: readonly SegmentSide[]\n /** Seconds of stagger left from a heavy hit. */\n readonly stunSeconds: number\n /** What the last `hit` did (points, kill, headshot, through). */\n readonly lastHit?: HitReport\n /** The bleeding wounds, oldest first. */\n bleeders(): readonly Readonly<Bleeder>[]\n /** 0..1 protection of the layers over a segment against a bite or a scratch (the layered T3 formula, capped at 90 %). */\n protectionAgainst(attack: 'bite' | 'scratch', part: SegmentId): number\n /** Ids of the protection layers worn and not used up (a helmet that took its shot is gone). */\n intactProtection(): readonly string[]\n /** Penetration resistance R of the path through a part (a segment or a region id), with the protection worn over it. */\n resistanceOf(part: string): number\n hit(hit: Hit | BodyHit): DestructionEvent[]\n /** Ages bleeders (a `leak` per second each) and the stun. */\n update(dt: number): DestructionEvent[]\n serialize(): unknown\n load(data: unknown): void\n }\n\nexport type DamageSetup = {\n readonly rules: DamageRules\n readonly model: PenetrationModel\n readonly protection: ReadonlyMap<string, ProtectionLayer>\n readonly calibers: ReadonlyMap<string, CaliberEntry>\n}\n\ntype Saved = { body: Omit<BodyState, 'consumed'> & { consumed: string[] }; bleeders: Bleeder[]; hitCounter: number; clock: number }\n\nexport const createDamageCharacter = (core: CharacterCore, setup: DamageSetup): DamageCharacter => {\n const view = characterView(core)\n const worn = core.spec.protection.map((id) => setup.protection.get(id)).filter((layer): layer is ProtectionLayer => layer !== undefined)\n let bleeders: Bleeder[] = []\n let hitCounter = 0\n let clock = 0\n let lastHit: HitReport | undefined\n const transform = () => ({ position: core.position, rotation: core.rotation })\n const jointOf = (id: SegmentId): Vec3 => core.rig.joints[segmentNode(id).joint]\n const pointOf = (id: SegmentId): Vec3 => toWorld(transform(), jointOf(id))\n const opsFor = (random: () => number, source?: string): BodyOps =>\n createBodyOps({ body: core.body, spec: core.spec, rules: setup.rules, random, time: clock, pointOf, bleeders, ...(source !== undefined ? { source } : {}) })\n\n const character: DamageCharacter = {\n ...view,\n get segments() {\n return core.body.segments\n },\n get detail() {\n return core.body.detail\n },\n get alive() {\n return core.body.alive\n },\n get limping() {\n return [...core.body.limping]\n },\n get stunSeconds() {\n return core.body.stunSeconds\n },\n get lastHit() {\n return lastHit\n },\n name: core.spec.kind,\n hit(raw) {\n const hit = raw as BodyHit\n hitCounter += 1\n const random = core.spec.random ?? createRng((core.spec.seed ^ hitCounter) >>> 0)\n const ops = opsFor(random, hit.source)\n lastHit = applyBlow({ ops, hit, setup, worn, localPoint: toLocal(transform(), hit.point), jointOf, describe: core.describe })\n return ops.events\n },\n update(dt) {\n clock += dt\n core.body.stunSeconds = Math.max(0, core.body.stunSeconds - dt)\n const ops = opsFor(() => 0)\n stepBleeding({ bleeders, dt, emit: ops.emit, pointOf })\n return ops.events\n },\n bleeders: () => bleeders.map((bleeder) => ({ ...bleeder })),\n intactProtection: () => core.spec.protection.filter((id) => !core.body.consumed.has(id)),\n resistanceOf(part) {\n const id = resolveSegment(core.body, core.describe(), part, [0, 0, 0])\n const layers = layersOn(worn, segmentNode(id).slots, core.body.consumed)\n const protection = layers.reduce((sum, layer) => sum + (layer.ballistic?.resistance ?? 0), 0)\n return segmentResistance({ kind: segmentNode(id).kind, bodyCount: core.spec.bodyCount, protection })\n },\n protectionAgainst: (attack, part) => layeredProtection({ layers: layersOn(worn, segmentNode(part).slots, core.body.consumed), attack }),\n reset() {\n core.resetBody()\n bleeders = []\n hitCounter = 0\n lastHit = undefined\n },\n serialize(): Saved {\n const { consumed, ...rest } = core.body\n return { body: { ...structuredClone(rest), consumed: [...consumed] }, bleeders: structuredClone(bleeders), hitCounter, clock }\n },\n load(data) {\n const saved = data as Saved\n Object.assign(core.body, structuredClone(saved.body), { consumed: new Set(saved.body.consumed) })\n bleeders = structuredClone(saved.bleeders)\n hitCounter = saved.hitCounter\n clock = saved.clock\n },\n }\n return character\n}\n","import type { DestructionEvent, Vec3 } from '@adatechnology/game-contracts'\n\nimport { isBodyRegion } from '../body/regions'\nimport { isSegmentId, segmentNode } from '../body/segment-tree'\nimport type { DamageCharacter } from './damage-character'\nimport { TEAM_GAME_RULES } from './defaults'\nimport { energyKept, teamGameCost, teamGameFalloff } from './penetration'\nimport { penetrationForce } from './points'\nimport type { CaliberEntry } from './types'\n\n/** One body in the line of fire, `distance` metres from the muzzle. */\nexport type LineTarget = { readonly character: DamageCharacter; readonly part: string; readonly distance: number; readonly point?: Vec3 }\n\n/** What the line needs from a shot (a `Shot` of game-weapons fits). */\nexport type LineShot = {\n readonly energyAt: (distance: number) => number\n /** Projectile grams. */\n readonly mass: number\n /** Diameter in mm. */\n readonly caliber: number\n readonly caliberId?: string\n readonly source?: string\n}\n\nexport type LineHit = { readonly index: number; readonly points: number; readonly energy: number; readonly killed: boolean; readonly headshot: boolean; readonly events: DestructionEvent[] }\nexport type LineResult = { readonly hits: LineHit[]; /** 1-based index of the last body hit (0: none). */ readonly stoppedAt: number }\n\nexport type PenetrateLineParams = {\n readonly model: 'physical' | 'team-game'\n readonly shot: LineShot\n readonly targets: readonly LineTarget[]\n readonly calibers: ReadonlyMap<string, CaliberEntry>\n}\n\n/** After a kill the game restarts the ray 0.3 m past the body and measures the next distances from there (`shootRay`). */\nconst RESTART_METRES = 0.3\n\nconst regionOfPart = (part: string) => (isSegmentId(part) ? segmentNode(part).region : isBodyRegion(part) ? part : 'torso')\n\nconst lineHit = (index: number, target: LineTarget, fields: { points: number; energy: number; events: DestructionEvent[] }): LineHit => ({\n index,\n ...fields,\n killed: !target.character.alive,\n headshot: target.character.lastHit?.headshot ?? false,\n})\n\n/** The game's `shootRay`: penetration points spent per body (head 0.7, torso 1, a brute 2, limb 0.5), 75 % of the damage carried on. */\nconst teamGameLine = ({ shot, targets, calibers }: PenetrateLineParams): LineResult => {\n const caliber = shot.caliberId === undefined ? undefined : calibers.get(shot.caliberId)\n if (caliber?.penetration === undefined || caliber.points === undefined) throw new Error(`game-characters: the team-game line needs a calibre with points and penetration (\"${shot.caliberId}\")`)\n let penetration = caliber.penetration\n let points = caliber.points\n let origin = 0\n const hits: LineHit[] = []\n for (const [index, target] of targets.entries()) {\n if (!target.character.alive || target.distance - origin <= 0) continue\n const distance = target.distance - origin\n const dealt = points * teamGameFalloff(distance, caliber.effectiveRangeMetres ?? Infinity)\n const events = target.character.hit({ type: 'ballistic', point: target.point ?? [0, 0, 0], part: target.part, points: dealt, caliberId: caliber.id, distance, ...(shot.source ? { source: shot.source } : {}) })\n hits.push(lineHit(index, target, { points: dealt, energy: shot.energyAt(target.distance), events }))\n penetration -= teamGameCost(regionOfPart(target.part), target.character.spec.bodyCount)\n points *= TEAM_GAME_RULES.damageKeptPerBody\n if (penetration <= 0) break\n if (!target.character.alive) origin = target.distance + RESTART_METRES\n }\n return { hits, stoppedAt: hits.length === 0 ? 0 : (hits[hits.length - 1]?.index ?? -1) + 1 }\n}\n\n/** P7: the force P = √(E·m/A) hits a body while it is above 0, loses the body's resistance R and keeps P/(P+R) of the energy. */\nconst physicalLine = ({ shot, targets }: PenetrateLineParams): LineResult => {\n const first = targets[0]\n let force = first ? penetrationForce(shot.energyAt(first.distance), shot.mass, shot.caliber) : 0\n let kept = 1\n const hits: LineHit[] = []\n for (const [index, target] of targets.entries()) {\n if (force <= 0) break\n if (!target.character.alive) continue\n const energy = shot.energyAt(target.distance) * kept\n const events = target.character.hit({ type: 'ballistic', point: target.point ?? [0, 0, 0], part: target.part, energy, mass: shot.mass, caliber: shot.caliber, distance: target.distance, ...(shot.caliberId ? { caliberId: shot.caliberId } : {}) })\n hits.push(lineHit(index, target, { points: target.character.lastHit?.points ?? 0, energy, events }))\n const resistance = target.character.resistanceOf(target.part)\n kept *= energyKept(force, resistance)\n force -= resistance\n }\n return { hits, stoppedAt: hits.length === 0 ? 0 : (hits[hits.length - 1]?.index ?? -1) + 1 }\n}\n\n/** A shot through a line of bodies, nearest first. Each body takes the hit through its own damage model. */\nexport const penetrateLine = (params: PenetrateLineParams): LineResult => (params.model === 'team-game' ? teamGameLine(params) : physicalLine(params))\n","type Entry = { readonly id: string }\n\n/** The shipped entries with the ones from `extra` added or, when the id exists, replaced. */\nexport const mergeById = <TEntry extends Entry>(shipped: readonly TEntry[], extra: readonly TEntry[] | undefined): Map<string, TEntry> => {\n const entries = new Map<string, TEntry>()\n for (const entry of [...shipped, ...(extra ?? [])]) entries.set(entry.id, entry)\n return entries\n}\n\n/** Applies `patch` by id (a shallow merge); a patch for an id that does not exist is ignored. */\nexport const applyPatches = <TEntry extends Entry>(entries: Map<string, TEntry>, patches: Readonly<Record<string, Partial<TEntry>>> | undefined): void => {\n for (const [id, patch] of Object.entries(patches ?? {})) {\n const entry = entries.get(id)\n if (entry) entries.set(id, { ...entry, ...patch, id })\n }\n}\n\nexport const removeIds = (entries: Map<string, unknown>, ids: readonly string[] | undefined): void => {\n for (const id of ids ?? []) entries.delete(id)\n}\n","import { createBodySpec } from './body/body-spec'\nimport { createCorpseLedger } from './corpses'\nimport type { CorpseLedger } from './corpses'\nimport type { BodySpec } from './body/body-spec'\nimport { createCharacterCore, resolveSpec } from './character'\nimport { createDamageCharacter } from './damage/damage-character'\nimport type { DamageCharacter } from './damage/damage-character'\nimport { DAMAGE_PRESETS, PROTECTION_PRESETS, TEAM_GAME_CALIBERS } from './damage/defaults'\nimport { penetrateLine } from './damage/line'\nimport type { LineResult, LineShot, LineTarget } from './damage/line'\nimport { PENETRATION_MODELS } from './damage/penetration'\nimport type { CaliberEntry, DamageRules, PenetrationModel, ProtectionLayer } from './damage/types'\nimport { applyPatches, mergeById, removeIds } from './registry'\nimport type { CharacterPreset, CharacterSpec, CharactersOptions, CorpseOptions, DamageOptions } from './types'\n\nexport const DEFAULT_CORPSES: CorpseOptions = { max: 400, seconds: 900 }\n\n/** The base preset every spec can start from: an unnamed adult person. */\nexport const PERSON_PRESET: CharacterPreset = { id: 'person', kind: 'person', age: 'adult' }\n\nexport type CharacterKit = {\n readonly body: BodySpec\n readonly presets: ReadonlyMap<string, CharacterPreset>\n readonly corpses: CorpseOptions\n readonly damage: DamageRules\n readonly penetration: PenetrationModel\n readonly protection: ReadonlyMap<string, ProtectionLayer>\n readonly calibers: ReadonlyMap<string, CaliberEntry>\n /** A new character: the preset (`spec.preset`, else the one named `spec.kind`) under the spec. */\n create(spec: CharacterSpec): DamageCharacter\n /** The bodies left on the ground, capped and timed by the kit's `corpses` option. */\n createCorpses<TData>(): CorpseLedger<TData>\n /** A shot through a line of bodies with the kit's penetration model and calibre table. */\n penetrateLine(shot: LineShot, targets: readonly LineTarget[]): LineResult\n}\n\n/** Fills a spec from its preset: what the spec says wins; `multipliers` merge field by field. */\nexport const applyPreset = (spec: CharacterSpec, presets: ReadonlyMap<string, CharacterPreset>): CharacterSpec => {\n const preset = presets.get(spec.preset ?? spec.kind)\n if (!preset) return spec\n const { id: _presetId, ...defaults } = preset\n const multipliers = { ...defaults.multipliers, ...spec.multipliers }\n return { ...defaults, ...spec, multipliers }\n}\n\n/** The rules of a preset (`kit` by default) with the given fields replaced; `severity`, `blast` and `segments` merge key by key. */\nexport const resolveDamageRules = (options: DamageOptions = {}): DamageRules => {\n const { preset, severity, blast, segments, ...rest } = options\n const base = DAMAGE_PRESETS[preset ?? 'kit']\n return { ...base, ...rest, severity: { ...base.severity, ...severity }, blast: { ...base.blast, ...blast }, segments: { ...base.segments, ...segments } }\n}\n\nconst modelOf = (option: CharactersOptions['penetration']): PenetrationModel => (typeof option === 'object' ? option : PENETRATION_MODELS[option ?? 'physical'])\n\nexport const createCharacters = (options: CharactersOptions = {}): CharacterKit => {\n const body = createBodySpec(options.body)\n const packs = options.packs ?? []\n const presets = mergeById([PERSON_PRESET], packs.flatMap((pack) => pack.presets ?? []))\n applyPatches(presets, options.patch)\n removeIds(presets, options.remove)\n const damage = resolveDamageRules(options.damage)\n const penetration = modelOf(options.penetration)\n const protection = mergeById(PROTECTION_PRESETS, [...packs.flatMap((pack) => pack.protection ?? []), ...(options.protection ?? [])])\n const shippedCalibers = penetration.id === 'team-game' ? TEAM_GAME_CALIBERS : []\n const calibers = mergeById(shippedCalibers, [...packs.flatMap((pack) => pack.calibers ?? []), ...(options.calibers ?? [])])\n const setup = { rules: damage, model: penetration, protection, calibers }\n let counter = 0\n return {\n body,\n presets,\n corpses: { ...DEFAULT_CORPSES, ...options.corpses },\n damage,\n penetration,\n protection,\n calibers,\n create(spec) {\n counter += 1\n const resolved = resolveSpec(applyPreset(spec, presets), body, counter)\n const core = createCharacterCore({ spec: resolved, bodySpec: body, hitPointsOf: (kind) => damage.segments[kind].hitPoints })\n return createDamageCharacter(core, setup)\n },\n createCorpses: () => createCorpseLedger({ ...DEFAULT_CORPSES, ...options.corpses }),\n penetrateLine: (shot, targets) => penetrateLine({ model: penetration.id === 'team-game' ? 'team-game' : 'physical', shot, targets, calibers }),\n }\n}\n","{\n \"cascade\": {\n \"hip\": 16,\n \"spine\": 11,\n \"shoulder\": 9,\n \"elbow\": 7,\n \"leg\": 14,\n \"knee\": 11,\n \"head\": 6\n },\n \"moves\": {\n \"idle\": {\n \"gait\": 0,\n \"freq\": 0,\n \"amp\": 0,\n \"knee\": 0,\n \"bob\": 0,\n \"lean\": 0,\n \"arm\": 0,\n \"elb\": 0.12,\n \"crouch\": 0,\n \"aim\": 0,\n \"turn\": 0,\n \"grip\": 0.35\n },\n \"walk\": {\n \"gait\": 1,\n \"freq\": 5.6,\n \"amp\": 0.42,\n \"knee\": 0.85,\n \"bob\": 0.035,\n \"lean\": 0.05,\n \"arm\": 0.42,\n \"elb\": 0.3,\n \"crouch\": 0,\n \"aim\": 0,\n \"turn\": 0,\n \"grip\": 0.4\n },\n \"run\": {\n \"gait\": 1,\n \"freq\": 9.2,\n \"amp\": 0.72,\n \"knee\": 1.5,\n \"bob\": 0.06,\n \"lean\": 0.3,\n \"arm\": 0.85,\n \"elb\": 1.35,\n \"crouch\": 0,\n \"aim\": 0,\n \"turn\": 0,\n \"grip\": 1.1\n },\n \"crouch\": {\n \"gait\": 1,\n \"freq\": 3.8,\n \"amp\": 0.3,\n \"knee\": 0.6,\n \"bob\": 0.02,\n \"lean\": 0.42,\n \"arm\": 0.15,\n \"elb\": 0.7,\n \"crouch\": 1,\n \"aim\": 0,\n \"turn\": 0,\n \"grip\": 0.8\n },\n \"aim\": {\n \"gait\": 0,\n \"freq\": 0,\n \"amp\": 0,\n \"knee\": 0,\n \"bob\": 0,\n \"lean\": 0.06,\n \"arm\": 0,\n \"elb\": 0.2,\n \"crouch\": 0.25,\n \"aim\": 1,\n \"turn\": 0,\n \"grip\": 1.2\n },\n \"turn\": {\n \"gait\": 0.5,\n \"freq\": 4.2,\n \"amp\": 0.14,\n \"knee\": 0.7,\n \"bob\": 0.012,\n \"lean\": 0.03,\n \"arm\": 0.12,\n \"elb\": 0.25,\n \"crouch\": 0,\n \"aim\": 0,\n \"turn\": 1,\n \"grip\": 0.4\n }\n },\n \"poses\": [\n {\n \"index\": 0,\n \"id\": \"walk\",\n \"name\": {\n \"pt-BR\": \"anda\"\n }\n },\n {\n \"index\": 1,\n \"id\": \"crawl\",\n \"name\": {\n \"pt-BR\": \"rasteja\"\n }\n },\n {\n \"index\": 2,\n \"id\": \"fallen\",\n \"name\": {\n \"pt-BR\": \"caído\"\n }\n },\n {\n \"index\": 3,\n \"id\": \"attack\",\n \"name\": {\n \"pt-BR\": \"ataca\"\n }\n },\n {\n \"index\": 4,\n \"id\": \"scream\",\n \"name\": {\n \"pt-BR\": \"grito\"\n }\n },\n {\n \"index\": 5,\n \"id\": \"crouch\",\n \"name\": {\n \"pt-BR\": \"agachado\"\n }\n },\n {\n \"index\": 6,\n \"id\": \"leap\",\n \"name\": {\n \"pt-BR\": \"salto\"\n }\n },\n {\n \"index\": 7,\n \"id\": \"eat\",\n \"name\": {\n \"pt-BR\": \"comendo\"\n }\n }\n ],\n \"walk\": {\n \"cadenceBase\": 0.5,\n \"cadencePerSpeed\": 0.3,\n \"stopBelowSpeed\": 0.05,\n \"maxSine\": 0.9,\n \"strideFactor\": 4,\n \"legLengthFactor\": 0.9\n }\n}\n","import gait from '../data/gait.json'\n\nconst WALK = gait.walk\n\n/** Cycles per second at `speed` m/s (the game's `walkCad`). */\nexport const walkCadence = (speed: number): number => WALK.cadenceBase + WALK.cadencePerSpeed * speed\n\n/** Hip swing in radians at `speed` m/s for a body `height` times the base height: the stride that makes the foot meet the ground (the game's `walkGait`). */\nexport const walkGait = (speed: number, height = 1): number =>\n speed < WALK.stopBelowSpeed ? 0 : 2 * Math.asin(Math.min(WALK.maxSine, speed / (WALK.strideFactor * WALK.legLengthFactor * height * walkCadence(speed))))\n\nexport type StrideParams = {\n readonly speed: number\n readonly height?: number\n /** Default true: cadence and swing come from the speed, so the feet do not slide. False keeps the profile's own numbers (the Bestiário preset). */\n readonly strideFromSpeed?: boolean\n}\n\nexport type Stride = {\n /** Cycles per second. */\n readonly frequency: number\n /** Thigh swing, radians. */\n readonly swing: number\n /** Knee bend, radians. */\n readonly kneeBend: number\n}\n\nconst SWING_SHARE = 0.5\nconst KNEE_PER_GAIT = 0.85\n\n/** The gait numbers for a speed: from the ground-matching stride, or `fallback` (the profile) when `strideFromSpeed` is false. */\nexport const strideFor = ({ speed, height = 1, strideFromSpeed = true }: StrideParams, fallback: Stride): Stride => {\n if (!strideFromSpeed) return fallback\n const amplitude = walkGait(speed, height)\n return { frequency: walkCadence(speed), swing: amplitude * SWING_SHARE, kneeBend: amplitude * KNEE_PER_GAIT }\n}\n","import gait from '../data/gait.json'\n\n/** How a body type walks: offsets over its rest pose (the Bestiário's `GAIT`). `f` cycles per second, `a` thigh swing, `k` knee bend, `arm` arm swing. */\nexport type GaitProfile = {\n readonly f: number\n readonly a?: number\n readonly k?: number\n readonly arm?: number\n readonly bob?: number\n readonly sway?: number\n readonly drag?: boolean\n readonly crawl?: boolean\n readonly idle?: boolean\n readonly eat?: boolean\n readonly leap?: boolean\n readonly listen?: boolean\n readonly stalk?: boolean\n readonly sniff?: boolean\n}\n\nexport type JointAngles = { readonly shoulder: number; readonly elbow: number }\nexport type LegAngles = { readonly hip: number; readonly knee: number; readonly lost?: boolean }\n\n/**\n * The pose the gait swings around. `arms[0]` is the right arm and `arms[1]` the left; `legs[0]` is the left leg and `legs[1]` the right\n * (the order the Bestiário builds them in). `hipY` is the rest height of the hips.\n */\nexport type RestPose = {\n readonly hipY: number\n readonly lean: number\n readonly headX: number\n readonly arms: readonly [JointAngles, JointAngles]\n readonly legs: readonly [LegAngles, LegAngles]\n}\n\n/** What a gait sets this frame; a field the gait does not write stays `undefined` and the joint keeps what it had. */\nexport type GaitSample = {\n hipY?: number\n upper: { x?: number; y?: number; z?: number }\n head: { x?: number; y?: number }\n arms: { shoulder?: number; elbow?: number }[]\n legs: { hip?: number; knee?: number }[]\n}\n\nexport const emptySample = (): GaitSample => ({ upper: {}, head: {}, arms: [{}, {}], legs: [{}, {}] })\n\nexport type CascadeJoint = keyof typeof gait.cascade\n\n/** Cascade rates per joint (1/s): each joint reaches its target with a delay, from the hips to the head (Bestiário 12.3). */\nexport const CASCADE: Readonly<Record<CascadeJoint, number>> = gait.cascade\n\n/** The 8 poses of the instanced body, in the order of the game's `iB.w`. */\nexport const INSTANCE_POSES = ['walk', 'crawl', 'fallen', 'attack', 'scream', 'crouch', 'leap', 'eat'] as const\nexport type InstancePose = (typeof INSTANCE_POSES)[number]\n\nconst MIN_HEIGHT = -2\nconst MAX_HEIGHT = 8\nconst HEIGHT_STEPS = 1000\nconst POSE_SLOTS = 16\n\n/** `iB.w` of the instanced body: the pose plus 16 times the ground height in millimetres (a pile of bodies, a jump). */\nexport const encodePoseHeight = (pose: InstancePose, height = 0): number =>\n INSTANCE_POSES.indexOf(pose) + POSE_SLOTS * Math.round((Math.min(MAX_HEIGHT, Math.max(MIN_HEIGHT, height)) - MIN_HEIGHT) * HEIGHT_STEPS)\n\nexport const decodePoseHeight = (encoded: number): { readonly pose: InstancePose; readonly height: number } => {\n const height = Math.floor(encoded / POSE_SLOTS) / HEIGHT_STEPS + MIN_HEIGHT\n return { pose: INSTANCE_POSES[encoded - Math.floor(encoded / POSE_SLOTS) * POSE_SLOTS] as InstancePose, height }\n}\n","import { emptySample } from './profile'\nimport type { GaitProfile, GaitSample, RestPose } from './profile'\nimport { strideFor } from './stride'\nimport type { StrideParams } from './stride'\n\nconst TWO_PI = Math.PI * 2\nconst LEAP_AIR_SHARE = 0.38\nconst LEAP_PHASE_DIVISOR = 6.3\nconst DEFAULT_PROFILE: GaitProfile = { f: 1.1, a: 0.28, k: 0.35, drag: true, arm: 0.08 }\n\nexport type AnimateProfileParams = {\n readonly profile?: GaitProfile\n readonly rest: RestPose\n /** Seconds. */\n readonly time: number\n /** Per-body phase offset, radians (the page's `rig.ph`). */\n readonly phase: number\n /** With `strideFromSpeed`, the speed and height that set cadence and swing. Without it the profile's own numbers are used. */\n readonly stride?: StrideParams\n}\n\n/** The leap, as a cycle: crouched, then airborne for 38% of it. */\nconst leap = ({ rest, time, phase, profile }: Required<Pick<AnimateProfileParams, 'rest' | 'time' | 'phase'>> & { profile: GaitProfile }): GaitSample => {\n const sample = emptySample()\n const cycle = (time * profile.f + phase / LEAP_PHASE_DIVISOR) % 1\n const air = cycle < LEAP_AIR_SHARE ? Math.sin((cycle / LEAP_AIR_SHARE) * Math.PI) : 0\n sample.hipY = rest.hipY + air * 0.95\n sample.upper.x = rest.lean - air * 0.45\n rest.legs.forEach((leg, index) => (sample.legs[index] = { hip: leg.hip * (1 - air * 0.7), knee: leg.knee * (1 - air * 0.75) }))\n rest.arms.forEach((arm, index) => (sample.arms[index] = { shoulder: arm.shoulder - air * 2.3, elbow: arm.elbow * (1 - air) }))\n return sample\n}\n\n/** Joint targets of one gait at `time` (the Bestiário's `animate0`), as numbers; the rig applies the ones that are set. */\nexport const animateProfile = ({ profile = DEFAULT_PROFILE, rest, time, phase, stride }: AnimateProfileParams): GaitSample => {\n const own = { frequency: profile.f, swing: profile.a ?? 0, kneeBend: profile.k ?? 0 }\n const { frequency, swing, kneeBend } = stride ? strideFor(stride, own) : own\n const angle = time * frequency * TWO_PI + phase\n const sine = Math.sin(angle)\n const cosine = Math.cos(angle)\n const sample = emptySample()\n if (profile.leap) return leap({ rest, time, phase, profile })\n if (profile.listen) {\n sample.head.y = Math.sin(time * 0.7 + phase) * 0.6\n rest.arms.forEach((arm, index) => (sample.arms[index] = { shoulder: arm.shoulder + Math.sin(time * 0.9 + index) * 0.08 }))\n return sample\n }\n if (profile.eat) {\n const wave = Math.sin(time * profile.f * TWO_PI + phase)\n sample.head.x = rest.headX + Math.max(0, wave) * 0.35\n sample.upper.x = rest.lean + Math.max(0, wave) * 0.08\n rest.arms.forEach((arm, index) => (sample.arms[index] = { elbow: arm.elbow + wave * 0.2 }))\n return sample\n }\n if (profile.crawl) {\n rest.arms.forEach((arm, index) => {\n const wave = index ? sine : -sine\n sample.arms[index] = { shoulder: arm.shoulder + wave * 0.35, elbow: arm.elbow - Math.max(0, wave) * 0.6 }\n })\n sample.upper.z = sine * 0.06\n return sample\n }\n if (profile.idle) {\n const scare = Math.max(0, Math.sin(time * 0.9 + phase))\n sample.upper.x = rest.lean - scare * 0.18\n sample.head.x = rest.headX - scare * 0.25\n rest.arms.forEach((arm, index) => (sample.arms[index] = { shoulder: arm.shoulder + scare * 0.25 }))\n return sample\n }\n rest.legs.forEach((leg, index) => {\n if (leg.lost) return\n const wave = index ? -sine : sine\n if (profile.drag && index === 1) return void (sample.legs[index] = { hip: leg.hip + wave * swing * 0.35, knee: leg.knee })\n sample.legs[index] = { hip: leg.hip + wave * swing, knee: leg.knee + Math.max(0, index ? cosine : -cosine) * kneeBend }\n })\n rest.arms.forEach((arm, index) => (sample.arms[index] = { shoulder: arm.shoulder + (index ? sine : -sine) * (profile.arm || 0.1) }))\n sample.hipY = rest.hipY - Math.abs(cosine) * (profile.bob || 0.02)\n sample.upper.y = sine * 0.06\n sample.upper.z = (profile.sway || 0) * sine + (profile.drag ? 0.04 : 0)\n if (profile.stalk) sample.upper.x = rest.lean + sine * 0.04\n if (profile.sniff) sample.head.y = Math.sin(time * 3.1 + phase) * 0.35\n return sample\n}\n","import { CASCADE } from './profile'\nimport type { CascadeJoint } from './profile'\n\n/** One joint moving toward its target: it covers `dt · rate` of the distance each step (never more than all of it). */\nexport const stepCascade = (current: number, target: number, dt: number, joint: CascadeJoint, rates: Readonly<Record<CascadeJoint, number>> = CASCADE): number =>\n current + (target - current) * Math.min(1, dt * rates[joint])\n\n/** Between two poses by joint name: a joint `from` does not name starts at the target (the Bestiário's `lerpPose`). */\nexport const lerpPose = <TPose extends Readonly<Record<string, number>>>(from: Partial<TPose>, to: TPose, amount: number): TPose => {\n const result: Record<string, number> = {}\n for (const name of Object.keys(to)) {\n const start = from[name]\n const end = to[name] as number\n result[name] = start === undefined ? end : (start as number) + (end - (start as number)) * amount\n }\n return result as TPose\n}\n","import gait from '../data/gait.json'\n\nexport type MoveId = keyof typeof gait.moves\nexport type MoveBlend = { gait: number; freq: number; amp: number; knee: number; bob: number; lean: number; arm: number; elb: number; crouch: number; aim: number; turn: number; grip: number }\n\n/** The human movement states the Elenco blends every frame. */\nexport const MOVES: Readonly<Record<MoveId, Readonly<MoveBlend>>> = gait.moves\n\nexport const MOVE_BLEND_RATE = 4\n\nexport const moveBlendOf = (move: MoveId): MoveBlend => ({ ...MOVES[move] })\n\n/** Moves `current` toward the target move: each number covers `dt · 4` of the distance (never past it). Mutates and returns `current`. */\nexport const blendMoves = (current: MoveBlend, target: MoveId | Readonly<MoveBlend>, dt: number): MoveBlend => {\n const goal = typeof target === 'string' ? MOVES[target] : target\n const amount = Math.min(1, dt * MOVE_BLEND_RATE)\n for (const key of Object.keys(goal) as (keyof MoveBlend)[]) current[key] += (goal[key] - current[key]) * amount\n return current\n}\n\nexport type HumanArm = { readonly side: 1 | -1; readonly hold?: boolean }\n\nexport type HumanPoseParams = {\n readonly moves: Readonly<MoveBlend>\n /** Seconds since the start. */\n readonly time: number\n /** The character's own phase offset. */\n readonly phase: number\n /** `phase + offset`: the walking cycle's angle, advanced by `dt · freq`. */\n readonly cycle: number\n /** The character's resting hunch plus the stage's. */\n readonly hunch: number\n /** The infection stage's arm raise (0 healthy .. 1 reanimated). */\n readonly armRaise: number\n /** Stage index: 3 and up adds a spine tremor, 4 is the reanimated body. */\n readonly stage: number\n /** The `prefers-reduced-motion` mode: no idle motion, no gait. */\n readonly reduced?: boolean\n readonly skirt?: boolean\n /** [right, left] as built: side and whether the hand holds an item. */\n readonly arms: readonly [HumanArm, HumanArm]\n /** [left, right] leg sides. */\n readonly legSides: readonly [1 | -1, 1 | -1]\n}\n\nexport type HumanPose = {\n readonly chestScaleY: number\n readonly hip: { readonly x: number; readonly y: number; readonly zRotation: number }\n readonly upper: { readonly x: number; readonly y: number; readonly z: number }\n readonly head: { readonly x: number; readonly y: number; readonly z: number }\n readonly legs: readonly { readonly hip: number; readonly knee: number; readonly hipZ: number }[]\n readonly arms: readonly { readonly shoulder: number; readonly shoulderZ: number; readonly elbow: number; readonly wrist: number; readonly grip: number }[]\n}\n\nconst REANIMATED_STAGE = 4\nconst TREMOR_STAGE = 3\n\n/** The blended walk of the Elenco for one frame (hips, spine, head, legs, arms), as joint targets. Pure: the caller keeps the phase and the blend. */\nexport const humanPose = (params: HumanPoseParams): HumanPose => {\n const { moves, time, phase, cycle, hunch, armRaise, stage, reduced = false, skirt = false } = params\n const zombie = stage === REANIMATED_STAGE\n const walking = reduced ? 0 : moves.gait\n const phased = phase + time\n const shift = reduced ? 0 : Math.sin(time * 0.45 + phase) * (1 - walking) * (1 - moves.aim)\n const upperX = hunch + moves.crouch * 0.15 + (stage >= TREMOR_STAGE && !reduced ? Math.sin(phased * 2.3) * 0.03 : 0)\n const upperY = walking * Math.sin(cycle - 0.35) * (0.08 + moves.arm * 0.12) - moves.aim * 0.35 + moves.turn * 0.25\n const upperZ = -shift * 0.025 + walking * Math.sin(cycle - 0.35) * 0.02 + (zombie ? 0.05 + Math.sin(cycle * 0.5) * 0.06 * walking : 0)\n const legs = params.legSides.map((side, index) => {\n const legCycle = cycle + (index ? Math.PI : 0)\n const amplitude = moves.amp * (zombie && index === 0 ? 0.45 : 1) * (skirt ? 0.75 : 1)\n return {\n hip: -walking * Math.sin(legCycle) * amplitude - moves.crouch * 0.95 + (zombie && !walking ? (index ? -0.1 : 0.08) : 0),\n knee:\n walking * (Math.max(0, Math.cos(legCycle)) * moves.knee * (zombie && index === 0 ? 0.3 : 1) + 0.06) +\n moves.crouch * 1.55 +\n (1 - walking) * (0.03 + Math.max(0, shift * (index ? 1 : -1)) * 0.18),\n hipZ: side * (0.02 + moves.aim * 0.1 + moves.crouch * 0.06),\n }\n })\n const arms = params.arms.map(({ side, hold = false }, index) => {\n const raise = armRaise * (hold && !zombie ? 0.2 : 1)\n const swing = cycle - 0.25\n const shoulderX =\n (hold ? -0.2 : 0) -\n raise * (zombie ? 1.12 : 1.3) -\n side * Math.sin(swing) * moves.arm * walking * (zombie ? 0.3 : 1) +\n (reduced || walking ? 0 : Math.sin(phased * 1.6 + side) * 0.04) +\n (zombie && !reduced ? Math.sin(phased * 3 + side * 2) * 0.08 : 0)\n const aimX = index === 0 ? -1.45 : -1.32\n return {\n shoulder: shoulderX * (1 - moves.aim) + aimX * moves.aim,\n shoulderZ: side * (0.07 + (zombie ? 0.1 : 0)) * (1 - moves.aim) - side * 0.32 * moves.aim,\n elbow: zombie ? -0.18 : -((moves.elb + (hold ? 0.25 : 0) + walking * Math.max(0, side * Math.sin(swing - 0.3)) * 0.3) * (1 - moves.aim) + (index === 0 ? 0.15 : 0.55) * moves.aim),\n wrist: reduced ? 0 : -walking * Math.sin(swing - 0.6) * 0.15 * side * (1 - moves.aim),\n grip: (hold ? 1.25 : moves.grip) * (zombie ? 0.5 : 1),\n }\n })\n const headY = (reduced ? 0 : Math.sin(phased * 0.5) * 0.25 * (1 - walking) * (1 - moves.aim) * (zombie ? 0.3 : 1)) - upperY * 0.75 * (1 - moves.turn) + moves.turn * 0.45 + moves.aim * 0.3\n return {\n chestScaleY: 1 + (reduced ? 0 : Math.sin(phased * (1.6 + moves.freq * 0.12)) * (0.012 + moves.freq * 0.0012)),\n hip: { x: shift * 0.025 + walking * Math.sin(cycle) * 0.018, y: -walking * moves.bob * Math.abs(Math.sin(cycle)) - moves.crouch * 0.26, zRotation: shift * 0.02 - walking * Math.sin(cycle) * 0.022 },\n upper: { x: upperX, y: upperY, z: upperZ },\n head: { x: -hunch * 0.6 - moves.crouch * 0.12 + (zombie ? 0.15 : 0) + walking * Math.sin(cycle * 2 - 0.6) * 0.02, y: headY, z: (zombie ? 0.22 : 0) - upperZ * 0.6 },\n legs,\n arms,\n }\n}\n\n/** A leg that cannot carry weight (limp): the swing shrinks to 30%, the knee straightens, the spine leans toward the good leg. */\nexport const LIMP = { swing: 0.3, knee: 0.05, lean: 0.07 } as const\n","/** Prone crawl on the arms (the Elenco's leg-less body): joint targets at `time`; `figTilt` is the body's tilt target, which the caller approaches at `dt · 4`. */\nexport type CrawlPose = {\n readonly figTilt: number\n readonly hipY: number\n readonly hipZRotation: number\n readonly upper: { readonly x: number; readonly y: number }\n readonly headX: number\n readonly arms: readonly { readonly shoulder: number; readonly shoulderZ: number; readonly elbow: number }[]\n readonly legs: readonly { readonly hip: number; readonly knee: number }[]\n}\n\nexport const CRAWL_TILT_RATE = 4\nexport const DEAD_TILT_RATE = 3\n\nexport const crawlPose = (time: number, phase: number, sides: readonly [1 | -1, 1 | -1]): CrawlPose => {\n const cycle = time * 2.2 + phase\n const wave = Math.sin(cycle)\n return {\n figTilt: 1.38,\n hipY: 0.2 + Math.abs(wave) * 0.02,\n hipZRotation: wave * 0.05,\n upper: { x: 0, y: wave * 0.12 },\n headX: -0.95,\n arms: sides.map((side) => ({ shoulder: -2.55 + side * wave * 0.45, shoulderZ: side * 0.25, elbow: -0.35 - Math.max(0, -side * wave) * 0.6 })),\n legs: [\n { hip: 0.1, knee: 0 },\n { hip: 0.12 + wave * 0.08, knee: 0.25 },\n ],\n }\n}\n\nexport type DeadPose = {\n readonly figTilt: number\n readonly hipY: number\n readonly headY: number\n readonly arms: readonly { readonly shoulder: number; readonly shoulderZ: number; readonly elbow: number }[]\n readonly legs: readonly { readonly hip: number; readonly hipZ: number; readonly knee: number }[]\n}\n\n/** A body on the ground (the Elenco's death pose); the caller approaches `figTilt` at `dt · 3`. */\nexport const deadPose = (armSides: readonly [1 | -1, 1 | -1]): DeadPose => ({\n figTilt: -1.45,\n hipY: 0.22,\n headY: 0.5,\n arms: armSides.map((side) => ({ shoulder: -0.2, shoulderZ: side * 1.1, elbow: -0.3 })),\n legs: [-0.15, 0.15].map((hipZ) => ({ hip: 0, hipZ, knee: 0.1 })),\n})\n","export type ConditionPhase = {\n readonly id: string\n /** When the phase starts, in the timeline's units (hours, or seconds on an accelerated clock). The first phase starts at 0. */\n readonly startsAt: number\n /** Numbers the phase drives (skin tint, hunch, arm raise, ...), by name. */\n readonly effects?: Readonly<Record<string, number>>\n}\n\nexport type ConditionOptions = {\n readonly phases: readonly ConditionPhase[]\n /** Timeline units per real second: 1 on a clock already in seconds (the accelerated preset), 1/3600 for hours. Default 1. */\n readonly unitsPerSecond?: number\n /** Interpolate effects toward the next phase instead of stepping. Default false. */\n readonly blend?: boolean\n}\n\nexport type ConditionSample = {\n readonly index: number\n readonly phase: ConditionPhase\n /** 0..1 inside the current phase (1 on the last one). */\n readonly progress: number\n readonly effects: Readonly<Record<string, number>>\n readonly isFinal: boolean\n}\n\nexport type ConditionTimeline = {\n readonly elapsed: number\n /** Advances the clock by `seconds` of real time. */\n advance(seconds: number): ConditionSample\n /** Jumps the clock to `units` of the timeline. */\n seek(units: number): ConditionSample\n sample(): ConditionSample\n reset(): void\n}\n\nconst phaseIndexAt = (phases: readonly ConditionPhase[], units: number): number => {\n let found = 0\n phases.forEach((phase, index) => {\n if (units >= phase.startsAt) found = index\n })\n return found\n}\n\nconst mixEffects = (from: ConditionPhase['effects'], to: ConditionPhase['effects'], amount: number): Record<string, number> => {\n const result: Record<string, number> = {}\n for (const name of new Set([...Object.keys(from ?? {}), ...Object.keys(to ?? {})])) {\n const start = from?.[name] ?? 0\n result[name] = start + ((to?.[name] ?? 0) - start) * amount\n }\n return result\n}\n\n/** A condition that moves through ordered phases over time (an infection: well, fever, delirium, reanimated). Generic: phases and effects are data. */\nexport const createConditionTimeline = (options: ConditionOptions): ConditionTimeline => {\n const { phases, unitsPerSecond = 1, blend = false } = options\n if (phases.length === 0) throw new Error('createConditionTimeline: at least one phase is required')\n let units = 0\n const sample = (): ConditionSample => {\n const index = phaseIndexAt(phases, units)\n const phase = phases[index] as ConditionPhase\n const next = phases[index + 1]\n const progress = next ? Math.min(1, (units - phase.startsAt) / (next.startsAt - phase.startsAt)) : 1\n const effects = blend && next ? mixEffects(phase.effects, next.effects, progress) : { ...phase.effects }\n return { index, phase, progress, effects, isFinal: !next }\n }\n return {\n get elapsed() {\n return units\n },\n advance(seconds) {\n units += seconds * unitsPerSecond\n return sample()\n },\n seek(target) {\n units = Math.max(0, target)\n return sample()\n },\n sample,\n reset() {\n units = 0\n },\n }\n}\n","{\n \"variance\": {\n \"height\": {\n \"gaussianSpread\": 0.09,\n \"min\": 0.9,\n \"max\": 1.1\n },\n \"buildBands\": [\n {\n \"below\": 0.3,\n \"base\": 0.85,\n \"range\": 0.1\n },\n {\n \"below\": 0.8,\n \"base\": 0.95,\n \"range\": 0.13\n },\n {\n \"base\": 1.08,\n \"range\": 0.17\n }\n ],\n \"buildSpeed\": {\n \"lean\": 1.05,\n \"heavy\": 0.9\n },\n \"buildHealth\": {\n \"lean\": 0.9,\n \"heavy\": 1.15\n },\n \"speedJitter\": {\n \"base\": 0.92,\n \"range\": 0.16\n },\n \"wanderJitter\": {\n \"base\": 0.8,\n \"range\": 0.4\n },\n \"runnerAgeClamp\": 1,\n \"variantCount\": {\n \"walker\": 4,\n \"runner\": 3,\n \"crawler\": 2,\n \"brute\": 2\n },\n \"variantSeedBase\": 7000\n },\n \"civilianColors\": [\n \"6D5A4A\",\n \"4D5D6B\",\n \"7A3B33\",\n \"5B6B4A\",\n \"8A7A5A\",\n \"3E4A5C\",\n \"6A4A6A\",\n \"9A8A70\",\n \"40403A\"\n ],\n \"corpses\": {\n \"max\": 400,\n \"lifeSeconds\": 900\n }\n}\n","import appearance from '../data/appearance.json'\n\nconst { variance } = appearance\n\nexport type BuildClass = 'lean' | 'average' | 'heavy'\n\n/** What `zSpawn` draws for a body: height, width, how it builds up and the speed jitters. Every field comes from the stream, in the game's order. */\nexport type BodyVariance = {\n readonly height: number\n readonly build: number\n readonly buildClass: BuildClass\n /** Multiplies the chase speed: the build factor times a 0.92 .. 1.08 jitter. */\n readonly speedFactor: number\n /** Multiplies the wander speed: 0.8 .. 1.2. */\n readonly wanderFactor: number\n /** Multiplies the health: 0.9 lean, 1.15 heavy. */\n readonly healthFactor: number\n}\n\nexport type VarianceScale = { readonly height?: number; readonly build?: number }\n\nconst clamp = (value: number, low: number, high: number): number => Math.min(high, Math.max(low, value))\n\n/**\n * One body's variance from `random`, drawing exactly what the game's `zSpawn` draws after the type, age and outfit picks:\n * three draws for the height (a gaussian), one for the build band plus one inside it, one for the speed and one for the wander speed.\n * `scale` is the type's own scale (a brute's 1.42) and `build` its width factor.\n */\nexport const drawBodyVariance = (random: () => number, scale: VarianceScale = {}): BodyVariance => {\n const spread = (random() + random() + random() - 1.5) * variance.height.gaussianSpread\n const height = clamp(1 + spread, variance.height.min, variance.height.max) * (scale.height ?? 1)\n const band = random()\n const bands = variance.buildBands as readonly { below?: number; base: number; range: number }[]\n const found = bands.find((candidate) => candidate.below !== undefined && band < candidate.below) ?? (bands[bands.length - 1] as { base: number; range: number })\n const { base, range } = found\n const build = (base + random() * range) * (scale.build ?? 1)\n const buildClass: BuildClass = band < 0.3 ? 'lean' : band >= 0.8 ? 'heavy' : 'average'\n const speedBuild = buildClass === 'lean' ? variance.buildSpeed.lean : buildClass === 'heavy' ? variance.buildSpeed.heavy : 1\n const healthBuild = buildClass === 'lean' ? variance.buildHealth.lean : buildClass === 'heavy' ? variance.buildHealth.heavy : 1\n return {\n height,\n build,\n buildClass,\n speedFactor: speedBuild * (variance.speedJitter.base + random() * variance.speedJitter.range),\n wanderFactor: variance.wanderJitter.base + random() * variance.wanderJitter.range,\n healthFactor: healthBuild,\n }\n}\n\n/** Variants baked per type (the game's `nv`): 4 walkers, 3 runners, 2 crawlers and brutes, 1 for the rest. */\nexport const variantCountFor = (typeId: string): number => (variance.variantCount as Readonly<Record<string, number>>)[typeId] ?? 1\n\n/** The seed of variant `variant` of the type at `typeIndex` (the game's ZVAR rule: `7000 + c·101 + v·13`). */\nexport const variantSeed = (typeIndex: number, variant: number): number => variance.variantSeedBase + typeIndex * 101 + variant * 13\n\n/** The decay each variant is baked at: 1, 2, 1, 2. */\nexport const variantDecay = (variant: number): number => (variant % 2 === 0 ? 1 : 2)\n","/** The colour and style pools of the Bestiário v17 builder, in the order its random stream picks from them. */\nexport const SKIN_TONES = [0xf1c9a5, 0xe0ac80, 0xc68c62, 0xa8714a, 0x8a5a3a, 0x5e3b26] as const\nexport const TOP_COLORS = [0x4a6f96, 0x8e3b3b, 0x5d4a3a, 0x4f7a43, 0x6b6f78, 0x3f5f3a, 0x5a4a6e, 0x8a6a3a, 0xb8b2a2, 0x2c2c30, 0x9a4a2a, 0x2f5d63, 0xc9a94a, 0x7a2e4a, 0xd8d4c8, 0x3a4a6a] as const\nexport const PANTS_COLORS = [0x2c3340, 0x1f2228, 0x4a4030, 0x5a5f66, 0x3a4a6a, 0x6a5a40, 0x2a3a2a] as const\nexport const SLEEVES = ['short', 'short', 'long', 'tank'] as const\nexport const HAIR_STYLES_FEMALE = ['long', 'long', 'bun', 'short', 'afro', 'bald'] as const\nexport const HAIR_STYLES_MALE = ['short', 'short', 'buzz', 'bald', 'afro', 'long'] as const\nexport const CAP_COLORS = [0x8e3b3b, 0x2c2c30, 0x3a4a6a, 0xc9a94a] as const\nexport const BAG_COLORS = [0x3a4a3a, 0x5a2a24, 0x2c3340] as const\nexport const HAIR_COLORS = [0x1a1410, 0x2a1e16, 0x3b2c20, 0x6a4a2a, 0xb08a50, 0x7a2a1a] as const\nexport const SHOE_COLORS = [0x1d1f22, 0x3a2a1a, 0xb8b4a8, 0x4a1a1a] as const\n/** Uniform bodies (the crowd's baked variants): skin by decay, shirt by type index. */\nexport const DECAY_SKIN = [0xcdbba8, 0x94a084, 0x7b744a, 0x8c7c5e] as const\nexport const UNIFORM_SHIRTS = [0x4a6f96, 0x8e3b3b, 0x5d4a3a, 0x4f7a43, 0x6b6f78, 0x3f5f3a, 0x5a4a6e, 0x8a6a3a] as const\nexport const UNIFORM_PANTS = 0x2c3340\nexport const UNIFORM_SHOES = 0x1d1f22\nexport const SKIN_DECAY_BLEND = [0.45, 0.65, 0.8, 0.88] as const\nexport const GRAY = 0x4a4a46\nexport const RED = 0x7a120c\nexport const BLOOD_COLORS = [0x9e1b12, 0x6e1410, 0x4a2a18, 0x1c1612] as const\nexport const OLD_HAIR = 0x8a8780\n","import { createRng } from '../damage/points'\n\nimport {\n BAG_COLORS,\n CAP_COLORS,\n DECAY_SKIN,\n HAIR_COLORS,\n HAIR_STYLES_FEMALE,\n HAIR_STYLES_MALE,\n OLD_HAIR,\n PANTS_COLORS,\n SHOE_COLORS,\n SKIN_TONES,\n SLEEVES,\n TOP_COLORS,\n UNIFORM_PANTS,\n UNIFORM_SHIRTS,\n UNIFORM_SHOES,\n} from './palette'\n\nexport type HairStyle = (typeof HAIR_STYLES_FEMALE)[number] | (typeof HAIR_STYLES_MALE)[number]\n\nexport type OutfitLook = { readonly cloth?: number; readonly pants?: number; readonly hat?: string }\n\nexport type AppearanceParams = {\n readonly seed: number\n /** The look of an outfit (police, military ...): its colours replace the draws, so the stream does not spend them. */\n readonly outfit?: OutfitLook\n /** A baked crowd variant: no random look, fixed skin, shirt by `typeIndex`, short hair. */\n readonly uniform?: boolean\n readonly typeIndex?: number\n readonly clothIndex?: number\n /** Forces the sex; unset draws it (42% female). */\n readonly female?: boolean\n /** False for bodies that are never female (a brute): the draw is skipped. */\n readonly allowFemale?: boolean\n readonly tone?: number\n readonly hairStyle?: HairStyle\n readonly hairColor?: number\n /** The type's own look: wet bodies have long hair, charred ones are bald. */\n readonly wet?: boolean\n readonly charred?: boolean\n /** A living person: no bag, no tear. */\n readonly human?: boolean\n /** 0 fresh-dead, 1 normal, 2 old (grey hair). */\n readonly life?: number\n}\n\nexport type AppearanceTraits = {\n readonly female: boolean\n readonly tone: number\n readonly topColor: number\n readonly pantsColor: number\n readonly sleeve: string\n readonly hair: string\n readonly headWidth: number\n readonly headHeight: number\n readonly jaw: number\n readonly nose: number\n readonly beard: boolean\n readonly glasses: boolean\n readonly cap: boolean\n readonly capColor: number\n readonly bag: boolean\n readonly bagColor: number\n readonly torn: boolean\n readonly apron: boolean\n readonly hairColor: number\n readonly shoeColor: number\n}\n\nexport type DrawnAppearance = {\n readonly traits: AppearanceTraits\n /** The stream, positioned after the look: the body builder keeps drawing from it (the hair of a decrepit body). */\n readonly random: () => number\n}\n\n/** The seed of the blood stream (the same drips on every level of detail). */\nexport const BLOOD_SEED_OFFSET = 99\n\nexport const createBloodStream = (seed: number): (() => number) => createRng(seed + BLOOD_SEED_OFFSET)\n\nconst FEMALE_SHARE = 0.42\nconst BEARD_SHARE = 0.25\nconst GLASSES_SHARE = 0.12\nconst CAP_SHARE = 0.12\nconst BAG_SHARE = 0.15\nconst TORN_SHARE = 0.35\nconst APRON_SHARE = 0.05\n\n/**\n * A person's look from a seed, drawing in exactly the order the Bestiário v17 builder draws from its `VR` stream, including the draws a\n * short-circuit skips (no beard roll for a woman, no cap roll under a hat). Returns the stream so the builder can continue from it.\n */\nexport const drawAppearance = (params: AppearanceParams): DrawnAppearance => {\n const { seed, outfit = {}, uniform = false, typeIndex = 0, human = false, life = 1 } = params\n const random = createRng(seed)\n const pick = <T>(options: readonly T[]): T => options[Math.floor(random() * options.length)] as T\n const female = !uniform && (params.allowFemale ?? true) && (params.female ?? random() < FEMALE_SHARE)\n const tone = params.tone ?? (uniform ? (DECAY_SKIN[0] as number) : pick(SKIN_TONES))\n const topColor = outfit.cloth ?? (uniform ? (UNIFORM_SHIRTS[(params.clothIndex ?? typeIndex) % UNIFORM_SHIRTS.length] as number) : pick(TOP_COLORS))\n const pantsColor = outfit.pants ?? (uniform ? UNIFORM_PANTS : pick(PANTS_COLORS))\n const look = uniform ? uniformLook() : drawLook({ random, pick, female, outfit, human, params })\n const hairColor = params.hairColor ?? (life === 2 ? OLD_HAIR : pick(HAIR_COLORS))\n const shoeColor = uniform ? UNIFORM_SHOES : pick(SHOE_COLORS)\n return { traits: { female, tone, topColor, pantsColor, ...look, hairColor, shoeColor }, random }\n}\n\ntype Look = Omit<AppearanceTraits, 'female' | 'tone' | 'topColor' | 'pantsColor' | 'hairColor' | 'shoeColor'>\n\nconst uniformLook = (): Look => ({\n sleeve: 'short',\n hair: 'short',\n headWidth: 1,\n headHeight: 1,\n jaw: 1,\n nose: 1,\n beard: false,\n glasses: false,\n cap: false,\n capColor: 0,\n bag: false,\n bagColor: 0,\n torn: false,\n apron: false,\n})\n\ntype DrawLookParams = {\n readonly random: () => number\n readonly pick: <T>(options: readonly T[]) => T\n readonly female: boolean\n readonly outfit: OutfitLook\n readonly human: boolean\n readonly params: AppearanceParams\n}\n\nconst drawLook = ({ random, pick, female, outfit, human, params }: DrawLookParams): Look => {\n const sleeve = outfit.cloth ? 'long' : pick(SLEEVES)\n const hair = params.hairStyle ?? (params.wet ? 'long' : params.charred ? 'bald' : pick(female ? HAIR_STYLES_FEMALE : HAIR_STYLES_MALE))\n const headWidth = 1 + (random() - 0.5) * 0.16\n const headHeight = 1 + (random() - 0.5) * 0.14\n const jaw = 1 + (random() - 0.5) * 0.3\n const nose = 1 + (random() - 0.5) * 0.5\n const beard = !female && random() < BEARD_SHARE\n const glasses = random() < GLASSES_SHARE\n const cap = !outfit.hat && random() < CAP_SHARE\n const capColor = pick(CAP_COLORS)\n const bag = random() < BAG_SHARE && !human\n const bagColor = pick(BAG_COLORS)\n const torn = random() < TORN_SHARE && !human\n const apron = random() < APRON_SHARE\n return { sleeve, hair, headWidth, headHeight, jaw, nose, beard, glasses, cap, capColor, bag, bagColor, torn, apron }\n}\n"],"mappings":"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","names":["isArm","limb","below","distance","MISSING_BITS","MISSING_BITS","blast","hitHead","hitLimb","distance","severity","blast","shoulderX"]}
|
|
1
|
+
{"version":3,"sources":["../src/data/body.json","../src/body/body-spec.ts","../src/corpses.ts","../src/body/body-state.ts","../src/presets/team-game.json","../src/body/regions.ts","../src/data/segments.json","../src/body/segment-tree.ts","../src/body/describe.ts","../src/body/object-state.ts","../src/body/rig.ts","../src/character.ts","../src/body/transform.ts","../src/damage/bleeding.ts","../src/damage/body-ops.ts","../src/presets/physical.json","../src/damage/defaults.ts","../src/damage/penetration.ts","../src/damage/rules/blow.ts","../src/damage/rules/regions.ts","../src/damage/points.ts","../src/damage/blast.ts","../src/damage/protection.ts","../src/damage/resolve-part.ts","../src/damage/rules/arsenal.ts","../src/damage/rules/elenco.ts","../src/damage/rules/kit.ts","../src/damage/pipeline.ts","../src/damage/damage-character.ts","../src/damage/line.ts","../src/registry.ts","../src/kit.ts","../src/data/gait.json","../src/gait/stride.ts","../src/gait/profile.ts","../src/gait/animate.ts","../src/gait/cascade.ts","../src/gait/moves.ts","../src/gait/lying.ts","../src/condition/timeline.ts","../src/data/appearance.json","../src/appearance/variance.ts","../src/appearance/palette.ts","../src/appearance/traits.ts","../src/pose-clips/pose-clip.ts","../src/presets/pose-clips.json","../src/pose-clips/registry.ts","../src/pose-clips/first-person-clip.ts"],"sourcesContent":["{\n \"guide\": {\n \"heightMetres\": 1.8,\n \"shoulderWidthMetres\": 0.61,\n \"shoulderWidthWomanMetres\": 0.57,\n \"shoulderHeightMetres\": 1.475,\n \"headToHeight\": 0.1667\n },\n \"teamGame\": {\n \"source\": \"G 65336 J (shoulders +-0.24 m)\",\n \"joints\": {\n \"quadril\": [\n 0,\n 0.95,\n 0\n ],\n \"pescoco\": [\n 0,\n 1.52,\n 0\n ],\n \"ombroE\": [\n -0.24,\n 1.44,\n 0\n ],\n \"ombroD\": [\n 0.24,\n 1.44,\n 0\n ],\n \"cotoveloE\": [\n -0.27,\n 1.13,\n 0\n ],\n \"cotoveloD\": [\n 0.27,\n 1.13,\n 0\n ],\n \"coxaE\": [\n -0.1,\n 0.92,\n 0\n ],\n \"coxaD\": [\n 0.1,\n 0.92,\n 0\n ],\n \"joelhoE\": [\n -0.1,\n 0.5,\n 0\n ],\n \"joelhoD\": [\n 0.1,\n 0.5,\n 0\n ]\n },\n \"heightMetres\": 1.8\n },\n \"lodDistancesMetres\": [\n 18,\n 55\n ],\n \"triangleBudget\": {\n \"lod0\": 2500,\n \"lod1\": 800,\n \"lod2\": 250\n }\n}\n","import type { SegmentKind, Vec3 } from '@adatechnology/game-contracts'\n\nimport body from '../data/body.json'\n\n/** The 17 joints of a body: one per segment, the point the segment hangs from. */\nexport type JointId =\n | 'hip'\n | 'spine'\n | 'neck'\n | 'head'\n | 'jaw'\n | 'shoulderL'\n | 'shoulderR'\n | 'elbowL'\n | 'elbowR'\n | 'wristL'\n | 'wristR'\n | 'hipL'\n | 'hipR'\n | 'kneeL'\n | 'kneeR'\n | 'ankleL'\n | 'ankleR'\n\nexport const JOINT_IDS: readonly JointId[] = ['hip', 'spine', 'neck', 'head', 'jaw', 'shoulderL', 'shoulderR', 'elbowL', 'elbowR', 'wristL', 'wristR', 'hipL', 'hipR', 'kneeL', 'kneeR', 'ankleL', 'ankleR']\n\n/**\n * Proportions of a body: joint positions in metres for a body of `heightMetres`, standing, feet on y = 0, facing +z, left side on +x.\n * `segmentRadius` is the radius of the capsule a segment is hit through.\n */\nexport type BodySpec = {\n readonly id: string\n readonly heightMetres: number\n readonly joints: Readonly<Record<JointId, Vec3>>\n readonly segmentRadius: Readonly<Record<SegmentKind, number>>\n}\n\nconst SEGMENT_RADIUS: Readonly<Record<SegmentKind, number>> = {\n head: 0.1,\n jaw: 0.05,\n neck: 0.06,\n torso: 0.17,\n pelvis: 0.16,\n upperArm: 0.085,\n forearm: 0.065,\n hand: 0.05,\n thigh: 0.1,\n shin: 0.08,\n foot: 0.05,\n}\n\nconst { guide } = body\nconst shoulderX = guide.shoulderWidthMetres / 2\nconst shoulderY = guide.shoulderHeightMetres\n\n/** The Elenco style guide body (1.80 m, shoulders 0.61 m at 1.475 m, head about 1/6 of the height): the default. */\nexport const GUIDE: BodySpec = {\n id: 'guide',\n heightMetres: guide.heightMetres,\n joints: {\n hip: [0, 0.92, 0],\n spine: [0, 1.05, 0],\n neck: [0, 1.56, 0],\n head: [0, 1.64, 0],\n jaw: [0, 1.66, 0.06],\n shoulderL: [shoulderX, shoulderY, 0],\n shoulderR: [-shoulderX, shoulderY, 0],\n elbowL: [shoulderX, shoulderY - 0.31, 0],\n elbowR: [-shoulderX, shoulderY - 0.31, 0],\n wristL: [shoulderX, shoulderY - 0.61, 0],\n wristR: [-shoulderX, shoulderY - 0.61, 0],\n hipL: [0.105, 0.9, 0],\n hipR: [-0.105, 0.9, 0],\n kneeL: [0.105, 0.48, 0],\n kneeR: [-0.105, 0.48, 0],\n ankleL: [0.105, 0.1, 0],\n ankleR: [-0.105, 0.1, 0],\n },\n segmentRadius: SEGMENT_RADIUS,\n}\n\nconst J = body.teamGame.joints\nconst below = (point: readonly number[], drop: number): Vec3 => [point[0], point[1] - drop, point[2]]\n\n/**\n * The game's crowd body (G 65336 `J`, shoulders ±0.24 m), kept for the goldens of the instanced path. `J` has no spine, head, jaw, wrist or\n * ankle: spine and head sit on the hip and neck bones (bones 0 and 1 of the game), the wrist and ankle one forearm and one shin below.\n */\nexport const TEAM_GAME: BodySpec = {\n id: 'team-game',\n heightMetres: body.teamGame.heightMetres,\n joints: {\n hip: J.quadril as Vec3,\n spine: J.quadril as Vec3,\n neck: J.pescoco as Vec3,\n head: J.pescoco as Vec3,\n jaw: [0, J.pescoco[1] + 0.08, 0.06],\n shoulderL: J.ombroE as Vec3,\n shoulderR: J.ombroD as Vec3,\n elbowL: J.cotoveloE as Vec3,\n elbowR: J.cotoveloD as Vec3,\n wristL: below(J.cotoveloE, 0.3),\n wristR: below(J.cotoveloD, 0.3),\n hipL: J.coxaE as Vec3,\n hipR: J.coxaD as Vec3,\n kneeL: J.joelhoE as Vec3,\n kneeR: J.joelhoD as Vec3,\n ankleL: below(J.joelhoE, 0.42),\n ankleR: below(J.joelhoD, 0.42),\n },\n segmentRadius: SEGMENT_RADIUS,\n}\n\n/** A body spec from `base` (default `GUIDE`) with the given fields replaced; `joints` and `segmentRadius` merge key by key. */\nexport const createBodySpec = (patch: Partial<BodySpec> = {}, base: BodySpec = GUIDE): BodySpec => ({\n id: patch.id ?? base.id,\n heightMetres: patch.heightMetres ?? base.heightMetres,\n joints: { ...base.joints, ...patch.joints },\n segmentRadius: { ...base.segmentRadius, ...patch.segmentRadius },\n})\n","import type { CorpseOptions } from './types'\n\nexport type CorpseEntry<TData> = {\n /** Seconds since it fell. */\n age: number\n readonly data: TData\n}\n\nexport type CorpseLedger<TData> = {\n readonly entries: readonly CorpseEntry<TData>[]\n readonly count: number\n /** Adds a corpse; when the ledger is full the oldest one is replaced. Returns the replaced data, if any. */\n add(data: TData): TData | undefined\n /** Ages every corpse by `dt` seconds and removes the ones past their life (swap with the last, like the game). Returns the removed data. */\n update(dt: number): TData[]\n /** Takes one corpse away (eaten, searched and dragged off): the last one moves into its place, like the game's `CP`. Returns its data. */\n remove(index: number): TData | undefined\n clear(): void\n}\n\n/** The bodies left on the ground: capped (400) and gone after a lifetime (900 s); generic over what each one carries. */\nexport const createCorpseLedger = <TData>(options: CorpseOptions): CorpseLedger<TData> => {\n const entries: CorpseEntry<TData>[] = []\n return {\n entries,\n get count() {\n return entries.length\n },\n add(data) {\n if (entries.length < options.max) {\n entries.push({ age: 0, data })\n return undefined\n }\n let oldest = 0\n for (let index = 1; index < entries.length; index++) if ((entries[index] as CorpseEntry<TData>).age > (entries[oldest] as CorpseEntry<TData>).age) oldest = index\n const replaced = (entries[oldest] as CorpseEntry<TData>).data\n entries[oldest] = { age: 0, data }\n return replaced\n },\n update(dt) {\n const removed: TData[] = []\n for (let index = 0; index < entries.length; index++) {\n const entry = entries[index] as CorpseEntry<TData>\n entry.age += dt\n if (entry.age <= options.seconds) continue\n removed.push(entry.data)\n entries[index] = entries[entries.length - 1] as CorpseEntry<TData>\n entries.pop()\n index--\n }\n return removed\n },\n remove(index) {\n const entry = entries[index]\n if (!entry) return undefined\n entries[index] = entries[entries.length - 1] as CorpseEntry<TData>\n entries.pop()\n return entry.data\n },\n clear() {\n entries.length = 0\n },\n }\n}\n","import { MISSING_BITS } from '@adatechnology/game-contracts'\nimport type { SegmentKind } from '@adatechnology/game-contracts'\n\nimport type { Detail, SegmentState } from '../types'\nimport { LIMB_REGIONS, REGION_HIT_POINTS, REGION_SEGMENTS } from './regions'\nimport type { LimbRegion } from './regions'\nimport { SEGMENT_TREE } from './segment-tree'\nimport type { SegmentId, SegmentSide } from './segment-tree'\n\n/** The mutable state of one body. Both detail levels live here: the 17 segments and the hit points of the 5 crowd regions. */\nexport type BodyState = {\n readonly segments: SegmentState[]\n readonly regions: Record<LimbRegion, number>\n vitality: number\n readonly maxVitality: number\n alive: boolean\n /** The game's `MISSING_BITS` mask. */\n missing: number\n /** Sides that limp, in the order they started. */\n readonly limping: SegmentSide[]\n crawl: boolean\n stunSeconds: number\n /** Loose pieces: each severed segment with what fell with it. */\n readonly pieces: SegmentId[][]\n /** Protection layers used up (a helmet that took its one shot). */\n readonly consumed: Set<string>\n detail: Detail\n}\n\nexport type CreateBodyStateParams = { readonly vitality: number; readonly detail: Detail; readonly crawling?: boolean; readonly hitPointsOf: (kind: SegmentKind) => number }\n\nexport const createBodyState = ({ vitality, detail, crawling, hitPointsOf }: CreateBodyStateParams): BodyState => ({\n segments: SEGMENT_TREE.map((node) => {\n const max = hitPointsOf(node.kind)\n return { id: node.id, kind: node.kind, region: node.region, hp: max, max, status: 'ok', attached: true, ...(node.side ? { side: node.side } : {}) }\n }),\n regions: { ...REGION_HIT_POINTS },\n vitality,\n maxVitality: vitality,\n alive: true,\n missing: 0,\n limping: [],\n crawl: crawling ?? false,\n stunSeconds: 0,\n pieces: [],\n consumed: new Set(),\n detail,\n})\n\nexport const segmentOf = (body: BodyState, id: SegmentId): SegmentState => {\n const segment = body.segments.find((candidate) => candidate.id === id)\n if (!segment) throw new Error(`game-characters: unknown segment \"${id}\"`)\n return segment\n}\n\nconst LIMB_MASK: readonly { readonly ids: readonly SegmentId[]; readonly lost: number; readonly broken: number }[] = [\n { ids: ['upperArmL', 'forearmL'], lost: MISSING_BITS.armL, broken: MISSING_BITS.armLBroken },\n { ids: ['upperArmR', 'forearmR'], lost: MISSING_BITS.armR, broken: MISSING_BITS.armRBroken },\n { ids: ['thighL', 'shinL'], lost: MISSING_BITS.legL, broken: MISSING_BITS.legLBroken },\n { ids: ['thighR', 'shinR'], lost: MISSING_BITS.legR, broken: MISSING_BITS.legRBroken },\n]\n\n/** The crowd mask the segments amount to: a lost head, jaw, arm or leg (upper or lower part), and a broken one still attached. */\nexport const missingFromSegments = (body: BodyState): number => {\n let mask = 0\n if (!segmentOf(body, 'head').attached) mask |= MISSING_BITS.head\n else if (!segmentOf(body, 'jaw').attached) mask |= MISSING_BITS.jaw\n for (const limb of LIMB_MASK) {\n const parts = limb.ids.map((id) => segmentOf(body, id))\n if (parts.some((part) => !part.attached)) mask |= limb.lost\n else if (parts.some((part) => part.status === 'broken')) mask |= limb.broken\n }\n return mask\n}\n\n/** Region hit points from the segments: the share of the region's segment hit points left, scaled to the region's own hit points. */\nexport const regionsFromSegments = (body: BodyState): void => {\n for (const region of LIMB_REGIONS) {\n const parts = REGION_SEGMENTS[region].map((id) => segmentOf(body, id))\n const left = parts.reduce((sum, part) => sum + (part.attached ? Math.max(0, part.hp) : 0), 0)\n const total = parts.reduce((sum, part) => sum + part.max, 0)\n body.regions[region] = (REGION_HIT_POINTS[region] * left) / total\n }\n body.missing |= missingFromSegments(body)\n}\n\n/** Segment hit points from the regions (the reverse is lossy: every segment of a region keeps the region's share). */\nexport const segmentsFromRegions = (body: BodyState): void => {\n for (const region of LIMB_REGIONS) {\n const share = Math.max(0, body.regions[region]) / REGION_HIT_POINTS[region]\n for (const id of REGION_SEGMENTS[region]) {\n const part = segmentOf(body, id)\n if (part.attached) part.hp = Math.min(part.hp, part.max * share)\n }\n }\n}\n","{\n \"id\": \"team-game\",\n \"segments\": {\n \"head\": 40,\n \"arm\": 60,\n \"leg\": 80\n },\n \"calibers\": {\n \"7_62x51\": {\n \"gameKey\": \"308\",\n \"name\": \"7,62×51 (.308)\",\n \"points\": 75,\n \"penetration\": 4,\n \"effectiveRangeMetres\": 600,\n \"noiseMetres\": 130,\n \"skullRange\": 1,\n \"class\": \"rifle\"\n },\n \"9x19\": {\n \"gameKey\": \"9x19\",\n \"name\": \"9×19 mm\",\n \"points\": 35,\n \"penetration\": 1.2,\n \"effectiveRangeMetres\": 35,\n \"noiseMetres\": 60,\n \"skullRange\": 1,\n \"class\": \"pistol\"\n },\n \"12ga_00buck\": {\n \"gameKey\": \"12ga\",\n \"name\": \"12 ga 00\",\n \"points\": 12,\n \"pellets\": 9,\n \"penetration\": 0.5,\n \"effectiveRangeMetres\": 15,\n \"noiseMetres\": 90,\n \"skullRange\": 8,\n \"class\": \"pistol\"\n },\n \"7_62x39\": {\n \"gameKey\": \"762x39\",\n \"name\": \"7,62×39 mm\",\n \"points\": 55,\n \"penetration\": 3,\n \"effectiveRangeMetres\": 250,\n \"noiseMetres\": 110,\n \"skullRange\": 1,\n \"class\": \"rifle\"\n }\n },\n \"regionCost\": {\n \"head\": 0.7,\n \"torso\": 1,\n \"bruteTorso\": 2,\n \"limb\": 0.5\n },\n \"damageKeptPerBody\": 0.75,\n \"falloff\": {\n \"fullAtRange\": 1,\n \"atTwiceRange\": 0.5\n },\n \"helmetAbsorbs\": \"pistol\",\n \"regions\": [\n \"head\",\n \"torso\",\n \"armL\",\n \"armR\",\n \"legL\",\n \"legR\"\n ]\n}\n","import type { BodyRegion } from '@adatechnology/game-contracts'\n\nimport teamGame from '../presets/team-game.json'\nimport type { SegmentId } from './segment-tree'\n\n/** The regions that keep their own hit points in the crowd model (the torso has none: torso hits go to vitality). */\nexport type LimbRegion = Exclude<BodyRegion, 'torso'>\n\nexport const LIMB_REGIONS: readonly LimbRegion[] = ['head', 'armL', 'armR', 'legL', 'legR']\n\n/** The game's region numbers (`SEG`): hit points of the head, of an arm and of a leg. */\nexport const REGION_HIT_POINTS: Readonly<Record<LimbRegion, number>> = {\n head: teamGame.segments.head,\n armL: teamGame.segments.arm,\n armR: teamGame.segments.arm,\n legL: teamGame.segments.leg,\n legR: teamGame.segments.leg,\n}\n\n/** The segments that make up each region, and the one that names it in events (the first). */\nexport const REGION_SEGMENTS: Readonly<Record<BodyRegion, readonly SegmentId[]>> = {\n head: ['head', 'jaw', 'neck'],\n torso: ['torso', 'pelvis'],\n armL: ['upperArmL', 'forearmL', 'handL'],\n armR: ['upperArmR', 'forearmR', 'handR'],\n legL: ['thighL', 'shinL', 'footL'],\n legR: ['thighR', 'shinR', 'footR'],\n}\n\nexport const BODY_REGIONS: readonly BodyRegion[] = ['head', 'torso', 'armL', 'armR', 'legL', 'legR']\n\nexport const isBodyRegion = (value: string): value is BodyRegion => (BODY_REGIONS as readonly string[]).includes(value)\n","{\n \"segments\": [\n {\n \"id\": \"head\",\n \"region\": \"head\",\n \"hitPoints\": 40,\n \"multiplier\": 3,\n \"bleed\": 40\n },\n {\n \"id\": \"jaw\",\n \"region\": \"head\",\n \"hitPoints\": 12,\n \"multiplier\": 2,\n \"bleed\": 8\n },\n {\n \"id\": \"neck\",\n \"region\": \"head\",\n \"hitPoints\": 25,\n \"multiplier\": 2,\n \"bleed\": 46\n },\n {\n \"id\": \"torso\",\n \"region\": \"torso\",\n \"hitPoints\": 150,\n \"multiplier\": 1,\n \"bleed\": 10\n },\n {\n \"id\": \"pelvis\",\n \"region\": \"torso\",\n \"hitPoints\": 90,\n \"multiplier\": 1,\n \"bleed\": 12\n },\n {\n \"id\": \"upperArm\",\n \"region\": \"arm\",\n \"hitPoints\": 45,\n \"multiplier\": 0.6,\n \"bleed\": 15\n },\n {\n \"id\": \"forearm\",\n \"region\": \"arm\",\n \"hitPoints\": 30,\n \"multiplier\": 0.6,\n \"bleed\": 8\n },\n {\n \"id\": \"hand\",\n \"region\": \"arm\",\n \"hitPoints\": 12,\n \"multiplier\": 0.6,\n \"bleed\": 3\n },\n {\n \"id\": \"thigh\",\n \"region\": \"leg\",\n \"hitPoints\": 55,\n \"multiplier\": 0.7,\n \"bleed\": 19\n },\n {\n \"id\": \"shin\",\n \"region\": \"leg\",\n \"hitPoints\": 40,\n \"multiplier\": 0.7,\n \"bleed\": 9\n },\n {\n \"id\": \"foot\",\n \"region\": \"leg\",\n \"hitPoints\": 15,\n \"multiplier\": 0.7,\n \"bleed\": 3\n }\n ],\n \"regions\": {\n \"head\": {\n \"hitPoints\": 40,\n \"segmentSum\": 77,\n \"scale\": 0.5195\n },\n \"arm\": {\n \"hitPoints\": 60,\n \"segmentSum\": 87,\n \"scale\": 0.6897\n },\n \"leg\": {\n \"hitPoints\": 80,\n \"segmentSum\": 110,\n \"scale\": 0.7273\n }\n },\n \"arsenalWeapons\": {\n \"pistola\": {\n \"n\": \"Pistola 9×19\",\n \"dmg\": 35,\n \"pel\": 1\n },\n \"fuzil\": {\n \"n\": \"Fuzil 7,62×39\",\n \"dmg\": 55,\n \"pel\": 1\n },\n \"escopeta\": {\n \"n\": \"Escopeta 12 ga\",\n \"dmg\": 12,\n \"pel\": 9\n },\n \"cinquenta\": {\n \"n\": \".50 BMG\",\n \"dmg\": 180,\n \"pel\": 1\n },\n \"granada\": {\n \"n\": \"Granada\",\n \"dmg\": 300,\n \"pel\": 0\n }\n },\n \"elenco\": {\n \"segments\": {\n \"head\": {\n \"hp\": 40,\n \"radius\": 0.07\n },\n \"torso\": {\n \"hp\": 120\n },\n \"pelvis\": {\n \"hp\": 90\n },\n \"upperArm\": {\n \"hp\": 60,\n \"radius\": 0.085\n },\n \"forearm\": {\n \"hp\": 45,\n \"radius\": 0.065\n },\n \"hand\": {\n \"hp\": 25,\n \"radius\": 0.05\n },\n \"thigh\": {\n \"hp\": 80,\n \"radius\": 0.1\n },\n \"shin\": {\n \"hp\": 55,\n \"radius\": 0.08\n }\n },\n \"below\": {\n \"upperArm\": [\n \"forearm\",\n \"hand\"\n ],\n \"forearm\": [\n \"hand\"\n ],\n \"thigh\": [\n \"shin\"\n ]\n },\n \"falls\": {\n \"upperArm\": \"o braço inteiro\",\n \"forearm\": \"o antebraço com a mão\",\n \"hand\": \"a mão\",\n \"thigh\": \"a perna inteira\",\n \"shin\": \"a canela com o pé\",\n \"head\": \"a cabeça\"\n },\n \"cutWeapons\": [\n {\n \"id\": \"faca\",\n \"n\": \"Faca\",\n \"dmg\": 22,\n \"cut\": 0.7\n },\n {\n \"id\": \"facao\",\n \"n\": \"Facão\",\n \"dmg\": 55,\n \"cut\": 1\n },\n {\n \"id\": \"machado\",\n \"n\": \"Machado\",\n \"dmg\": 85,\n \"cut\": 1\n },\n {\n \"id\": \"p9\",\n \"n\": \"Pistola 9 mm\",\n \"dmg\": 30,\n \"cut\": 0.15\n },\n {\n \"id\": \"e12\",\n \"n\": \"Espingarda 12\",\n \"dmg\": 95,\n \"cut\": 0.75\n },\n {\n \"id\": \"f762\",\n \"n\": \"Fuzil 7,62\",\n \"dmg\": 65,\n \"cut\": 0.45\n }\n ]\n },\n \"severity\": {\n \"severAtCut\": 0.5,\n \"severAtDamageFraction\": 0.9,\n \"destroyAtDamageMultiple\": 2,\n \"limpAtHpFraction\": 0.5,\n \"splitAtDamage\": 150,\n \"headKillDamage\": 20,\n \"jawChance\": 0.3,\n \"jawDamage\": 25,\n \"headBitDamage\": 60,\n \"headBitShotgunMetres\": 5\n },\n \"defaultCut\": {\n \"slash\": 0.85,\n \"blunt\": 0,\n \"explosive\": 1,\n \"ballistic\": {\n \"pistol\": 0.15,\n \"buckshot\": 0.75,\n \"rifle\": 0.45\n }\n },\n \"deathRule\": {\n \"default\": \"vitality-or-head\",\n \"options\": [\n \"vitality-or-head\",\n \"head-only\"\n ]\n }\n}\n","import type { BodyRegion, BodySlot, SegmentKind } from '@adatechnology/game-contracts'\n\nimport segments from '../data/segments.json'\nimport type { JointId } from './body-spec'\n\nexport type SegmentSide = 'L' | 'R'\ntype LimbKind = 'upperArm' | 'forearm' | 'hand' | 'thigh' | 'shin' | 'foot'\nexport type SegmentId = 'pelvis' | 'torso' | 'neck' | 'head' | 'jaw' | `${LimbKind}${SegmentSide}`\n\n/** One segment of the tree: the joint it hangs from, its parent, the crowd region it belongs to and the item slots that cover it. */\nexport type SegmentNode = {\n readonly id: SegmentId\n readonly kind: SegmentKind\n readonly side?: SegmentSide\n readonly joint: JointId\n readonly parent?: SegmentId\n readonly region: BodyRegion\n readonly slots: readonly BodySlot[]\n}\n\n/** Numbers of a segment kind (the Arsenal table, A4): hit points, damage multiplier and bleed rate. */\nexport type SegmentNumbers = { readonly hitPoints: number; readonly multiplier: number; readonly bleed: number }\n\nconst limb = (kind: LimbKind, side: SegmentSide, joint: JointId, parent: SegmentId | undefined, slots: readonly BodySlot[]): SegmentNode => {\n const isArm = kind === 'upperArm' || kind === 'forearm' || kind === 'hand'\n const region: BodyRegion = isArm ? (side === 'L' ? 'armL' : 'armR') : side === 'L' ? 'legL' : 'legR'\n return { id: `${kind}${side}`, kind, side, joint, region, slots, ...(parent ? { parent } : {}) }\n}\n\nconst sideOf = (side: SegmentSide): SegmentNode[] => [\n limb('upperArm', side, `shoulder${side}`, 'torso', ['arms']),\n limb('forearm', side, `elbow${side}`, `upperArm${side}`, ['arms']),\n limb('hand', side, `wrist${side}`, `forearm${side}`, ['hands']),\n limb('thigh', side, `hip${side}`, 'pelvis', ['legs']),\n limb('shin', side, `knee${side}`, `thigh${side}`, ['legs']),\n limb('foot', side, `ankle${side}`, `shin${side}`, ['feet']),\n]\n\n/** The 17 segments (11 kinds, limbs on both sides), parents before children. Neck and jaw have no item slot: a helmet does not cover them. */\nexport const SEGMENT_TREE: readonly SegmentNode[] = [\n { id: 'pelvis', kind: 'pelvis', joint: 'hip', region: 'torso', slots: ['torso'] },\n { id: 'torso', kind: 'torso', joint: 'spine', parent: 'pelvis', region: 'torso', slots: ['torso'] },\n { id: 'neck', kind: 'neck', joint: 'neck', parent: 'torso', region: 'head', slots: [] },\n { id: 'head', kind: 'head', joint: 'head', parent: 'neck', region: 'head', slots: ['head', 'eyes'] },\n { id: 'jaw', kind: 'jaw', joint: 'jaw', parent: 'head', region: 'head', slots: [] },\n ...sideOf('L'),\n ...sideOf('R'),\n]\n\nexport const SEGMENT_IDS: readonly SegmentId[] = SEGMENT_TREE.map((node) => node.id)\n\nconst NODES = new Map(SEGMENT_TREE.map((node) => [node.id, node]))\n\nexport const segmentNode = (id: SegmentId): SegmentNode => {\n const node = NODES.get(id)\n if (!node) throw new Error(`game-characters: unknown segment \"${id}\"`)\n return node\n}\n\nexport const isSegmentId = (value: string): value is SegmentId => NODES.has(value as SegmentId)\n\n/** Every segment that hangs below `id` (children, grandchildren...), in tree order: what falls with it when it is severed. */\nexport const segmentsBelow = (id: SegmentId): SegmentId[] => {\n const out: SegmentId[] = []\n const visit = (parent: SegmentId): void => {\n for (const node of SEGMENT_TREE) {\n if (node.parent !== parent) continue\n out.push(node.id)\n visit(node.id)\n }\n }\n visit(id)\n return out\n}\n\n/** The Arsenal numbers per segment kind (hit points, `MULT`, `BLEED`). */\nexport const SEGMENT_NUMBERS: Readonly<Record<SegmentKind, SegmentNumbers>> = Object.fromEntries(\n segments.segments.map((entry) => [entry.id, { hitPoints: entry.hitPoints, multiplier: entry.multiplier, bleed: entry.bleed }]),\n) as Record<SegmentKind, SegmentNumbers>\n","import type { DestructibleSpec, JointSpec, PartShape, PartSpec, SegmentKind, Vec3 } from '@adatechnology/game-contracts'\n\nimport type { BodySpec } from './body-spec'\nimport type { Rig } from './rig'\nimport { SEGMENT_TREE } from './segment-tree'\nimport type { SegmentNode } from './segment-tree'\n\n/** The material id the parts of a body carry (a destruction world without it skips its own material rules: the body is a `DestructibleImpl`). */\nexport const BODY_MATERIAL = 'flesh'\n\n/** Share of the body mass per segment kind (sums to 1 over the 17 segments). */\nconst MASS_SHARE: Readonly<Record<SegmentKind, number>> = {\n head: 0.07,\n jaw: 0.01,\n neck: 0.02,\n torso: 0.34,\n pelvis: 0.14,\n upperArm: 0.028,\n forearm: 0.016,\n hand: 0.006,\n thigh: 0.1,\n shin: 0.045,\n foot: 0.015,\n}\nconst ADULT_MASS_KG = 70\nconst LEAF_KINDS: ReadonlySet<SegmentKind> = new Set(['head', 'jaw', 'hand', 'foot'])\n\nconst firstChild = (node: SegmentNode): SegmentNode | undefined => SEGMENT_TREE.find((candidate) => candidate.parent === node.id)\n\n/** A cylinder from `from` to `to`: centred between them, its local +Y turned onto the segment (Euler XYZ). */\nconst cylinderBetween = (from: Vec3, to: Vec3, radius: number): { shape: PartShape; position: Vec3; rotation: Vec3 } => {\n const axis: Vec3 = [to[0] - from[0], to[1] - from[1], to[2] - from[2]]\n const length = Math.max(1e-3, Math.hypot(axis[0], axis[1], axis[2]))\n const [x, y, z] = [axis[0] / length, axis[1] / length, axis[2] / length]\n return {\n shape: { kind: 'cylinder', radius, height: length },\n position: [(from[0] + to[0]) / 2, (from[1] + to[1]) / 2, (from[2] + to[2]) / 2],\n rotation: [Math.atan2(z, y), 0, -Math.asin(Math.max(-1, Math.min(1, x)))],\n }\n}\n\nconst partOf = (node: SegmentNode, rig: Rig, body: BodySpec, massKg: number): PartSpec => {\n const joint = rig.joints[node.joint]\n const radius = body.segmentRadius[node.kind] * (rig.height / body.heightMetres)\n const mass = massKg * MASS_SHARE[node.kind]\n const child = firstChild(node)\n if (LEAF_KINDS.has(node.kind) || !child) {\n const lift = node.kind === 'head' ? radius : node.kind === 'jaw' ? 0 : -radius\n return { id: node.id, material: BODY_MATERIAL, shape: { kind: 'sphere', radius }, position: [joint[0], joint[1] + lift, joint[2]], mass, tags: ['body', node.kind] }\n }\n const placed = cylinderBetween(joint, rig.joints[child.joint], radius)\n return { id: node.id, material: BODY_MATERIAL, ...placed, mass, tags: ['body', node.kind] }\n}\n\nexport type DescribeBodyParams = { readonly rig: Rig; readonly body: BodySpec; readonly build: number; readonly name?: string }\n\n/** The body as destruction parts (one per segment, in the body's local space) and the joints between them. */\nexport const describeBody = ({ rig, body, build, name }: DescribeBodyParams): DestructibleSpec => {\n const massKg = ADULT_MASS_KG * (rig.height / body.heightMetres) ** 3 * build\n const parts = SEGMENT_TREE.map((node) => partOf(node, rig, body, massKg))\n const joints: JointSpec[] = SEGMENT_TREE.filter((node) => node.parent).map((node) => ({ id: `${node.parent}~${node.id}`, a: node.parent as string, b: node.id, kind: 'fused', tools: [] }))\n return { ...(name ? { name } : {}), parts, joints, tags: ['character'] }\n}\n","import type { DestructibleSpec, JointState, ObjectState, PartState, PartStatus, Quat, Vec3 } from '@adatechnology/game-contracts'\n\nimport type { SegmentStatus } from '../types'\nimport { missingFromSegments } from './body-state'\nimport type { BodyState } from './body-state'\n\nconst PART_STATUS: Readonly<Record<SegmentStatus, PartStatus>> = { ok: 'intact', wounded: 'damaged', broken: 'damaged', severed: 'collapsed', destroyed: 'broken' }\nconst BODY_TEMPERATURE_C = 37\n\nexport type ToObjectStateParams = {\n readonly id: string\n readonly name?: string\n readonly position: Vec3\n readonly rotation: Quat\n readonly body: BodyState\n readonly spec: DestructibleSpec\n}\n\n/** The body in the destruction contract: one part per segment, the joints between them, the pieces and the `body` summary. */\nexport const toObjectState = ({ id, name, position, rotation, body, spec }: ToObjectStateParams): ObjectState => {\n const groups: string[][] = [body.segments.filter((segment) => segment.attached).map((segment) => segment.id)]\n for (const piece of body.pieces) {\n const left = piece.filter((part) => body.segments.find((segment) => segment.id === part)?.status !== 'destroyed')\n if (left.length > 0) groups.push(left)\n }\n const groupOf = (part: string): number => groups.findIndex((group) => group.includes(part))\n const parts: PartState[] = body.segments.map((segment) => {\n const mass = spec.parts.find((part) => part.id === segment.id)?.mass ?? 0\n return {\n id: segment.id,\n material: 'flesh',\n status: PART_STATUS[segment.status],\n hp: Math.max(0, segment.hp),\n maxHp: segment.max,\n mass,\n temperature: BODY_TEMPERATURE_C,\n burning: false,\n fuel: 0,\n char: 0,\n melt: 0,\n dents: [],\n holes: [],\n cracks: [],\n group: groupOf(segment.id),\n }\n })\n const joints: JointState[] = (spec.joints ?? []).map((joint) => {\n const child = body.segments.find((segment) => segment.id === joint.b)\n const parent = body.segments.find((segment) => segment.id === joint.a)\n const open = child !== undefined && parent !== undefined && parent.attached !== child.attached\n return { id: joint.id ?? `${joint.a}~${joint.b}`, a: joint.a, b: joint.b, kind: joint.kind, hp: open ? 0 : 1, maxHp: 1, progress: 0, open, ...(open ? { openedBy: 'break' as const } : {}) }\n })\n return {\n id,\n ...(name ? { name } : {}),\n position: [...position],\n rotation: [...rotation],\n parts,\n joints,\n groups,\n destroyed: false,\n body: { alive: body.alive, vitality: body.vitality, missing: body.detail === 'segments' ? body.missing | missingFromSegments(body) : body.missing, limp: body.limping.length > 0, crawl: body.crawl },\n }\n}\n","import type { Vec3 } from '@adatechnology/game-contracts'\n\nimport { JOINT_IDS } from './body-spec'\nimport type { BodySpec, JointId } from './body-spec'\n\n/** The bones of the game's instanced body (G 65336): 0 torso and hip, 1 head, 2/3 arms, 4/5 thighs, 6 eyes, 7/8 forearms, 9/10 shins, 11 jaw. */\nexport const GAME_BONES = {\n torso: 0,\n head: 1,\n upperArmL: 2,\n upperArmR: 3,\n thighL: 4,\n thighR: 5,\n eyes: 6,\n forearmL: 7,\n forearmR: 8,\n shinL: 9,\n shinR: 10,\n jaw: 11,\n} as const\n\nexport const JOINT_PARENTS: Readonly<Record<JointId, JointId | undefined>> = {\n hip: undefined,\n spine: 'hip',\n neck: 'spine',\n head: 'neck',\n jaw: 'head',\n shoulderL: 'spine',\n shoulderR: 'spine',\n elbowL: 'shoulderL',\n elbowR: 'shoulderR',\n wristL: 'elbowL',\n wristR: 'elbowR',\n hipL: 'hip',\n hipR: 'hip',\n kneeL: 'hipL',\n kneeR: 'hipR',\n ankleL: 'kneeL',\n ankleR: 'kneeR',\n}\n\n/** The joints of one body, scaled to its height and build. */\nexport type Rig = {\n readonly joints: Readonly<Record<JointId, Vec3>>\n readonly parents: Readonly<Record<JointId, JointId | undefined>>\n readonly gameBones: typeof GAME_BONES\n /** Height in metres of this body. */\n readonly height: number\n}\n\nexport type CreateRigParams = { readonly body: BodySpec; readonly height: number; readonly build: number }\n\n/** Joints of `body` scaled to `height` metres (vertical and depth) and to `build` (width). */\nexport const createRig = ({ body, height, build }: CreateRigParams): Rig => {\n const scale = height / body.heightMetres\n const joints = Object.fromEntries(\n JOINT_IDS.map((id) => {\n const [x, y, z] = body.joints[id]\n return [id, [x * scale * build, y * scale, z * scale] as Vec3]\n }),\n ) as Record<JointId, Vec3>\n return { joints, parents: JOINT_PARENTS, gameBones: GAME_BONES, height }\n}\n","import type { DestructibleSpec, ObjectState, Quat, Vec3 } from '@adatechnology/game-contracts'\n\nimport type { BodySpec } from './body/body-spec'\nimport { createBodyState, regionsFromSegments, segmentsFromRegions } from './body/body-state'\nimport type { BodyState } from './body/body-state'\nimport { describeBody } from './body/describe'\nimport { toObjectState } from './body/object-state'\nimport type { LimbRegion } from './body/regions'\nimport { createRig } from './body/rig'\nimport type { Rig } from './body/rig'\nimport { SEGMENT_NUMBERS } from './body/segment-tree'\nimport type { BodyMultipliers, CharacterSpec, Detail, SegmentState } from './types'\n\n/** A spec with every default filled in. */\nexport type ResolvedCharacterSpec = CharacterSpec & {\n readonly id: string\n readonly height: number\n readonly build: number\n readonly vitality: number\n readonly multipliers: BodyMultipliers\n readonly limbFactor: number\n readonly bloodFactor: number\n readonly bodyCount: number\n readonly stunSeconds: number\n readonly protection: readonly string[]\n readonly detail: Detail\n}\n\nexport type Character = {\n readonly id: string\n readonly spec: ResolvedCharacterSpec\n readonly rig: Rig\n /** Live view of the 17 segments. */\n readonly segments: readonly SegmentState[]\n readonly detail: Detail\n /** Hit points of the 5 crowd regions (head, arms, legs). */\n regionHitPoints(): Readonly<Record<LimbRegion, number>>\n /** Swaps the detail level: segments to regions sums each region (lossless); regions to segments spreads the region's share (lossy). */\n setDetail(detail: Detail): void\n setTransform(position: Vec3, rotation?: Quat): void\n describe(): DestructibleSpec\n state(): ObjectState\n reset(): void\n}\n\nexport const DEFAULT_VITALITY = 100\nexport const DEFAULT_STUN_SECONDS = 0.45\nconst NO_MULTIPLIERS: BodyMultipliers = { head: 1, torso: 1, arms: 1, legs: 1 }\n\nexport const resolveSpec = (spec: CharacterSpec, body: BodySpec, counter: number): ResolvedCharacterSpec => ({\n ...spec,\n id: spec.id ?? `${spec.kind}_${counter}`,\n height: spec.height ?? body.heightMetres,\n build: spec.build ?? 1,\n vitality: spec.vitality ?? DEFAULT_VITALITY,\n multipliers: { ...NO_MULTIPLIERS, ...spec.multipliers },\n limbFactor: spec.limbFactor ?? 1,\n bloodFactor: spec.bloodFactor ?? 1,\n bodyCount: spec.bodyCount ?? 1,\n stunSeconds: spec.stunSeconds ?? DEFAULT_STUN_SECONDS,\n protection: spec.protection ?? [],\n detail: spec.detail ?? 'segments',\n})\n\nexport type CharacterCore = {\n readonly spec: ResolvedCharacterSpec\n readonly rig: Rig\n readonly body: BodyState\n position: Vec3\n rotation: Quat\n readonly describe: () => DestructibleSpec\n /** Back to the state at creation (full health, every segment attached). */\n readonly resetBody: () => void\n}\n\nexport type CreateCharacterCoreParams = { readonly spec: ResolvedCharacterSpec; readonly bodySpec: BodySpec; readonly hitPointsOf?: (kind: SegmentState['kind']) => number }\n\n/** The state every character shares: rig, body state, transform and the cached part list. */\nexport const createCharacterCore = ({ spec, bodySpec, hitPointsOf }: CreateCharacterCoreParams): CharacterCore => {\n const rig = createRig({ body: bodySpec, height: spec.height, build: spec.build })\n const parts = describeBody({ rig, body: bodySpec, build: spec.build, name: spec.kind })\n const fresh = (): BodyState => createBodyState({ vitality: spec.vitality, detail: spec.detail, crawling: spec.crawling ?? false, hitPointsOf: hitPointsOf ?? ((kind) => SEGMENT_NUMBERS[kind].hitPoints) })\n const body = fresh()\n return { spec, rig, body, position: [0, 0, 0], rotation: [0, 0, 0, 1], describe: () => parts, resetBody: () => void Object.assign(body, fresh()) }\n}\n\n/** The plain-data part of a character (state, detail and transform); the damage model is added on top of it. */\nexport const characterView = (core: CharacterCore): Character => ({\n id: core.spec.id,\n spec: core.spec,\n rig: core.rig,\n get segments() {\n return core.body.segments\n },\n get detail() {\n return core.body.detail\n },\n regionHitPoints: () => ({ ...core.body.regions }),\n setDetail(detail) {\n if (detail === core.body.detail) return\n if (detail === 'regions') regionsFromSegments(core.body)\n else segmentsFromRegions(core.body)\n core.body.detail = detail\n },\n setTransform(position, rotation) {\n core.position = [...position]\n if (rotation) core.rotation = [...rotation]\n },\n describe: core.describe,\n state: () => toObjectState({ id: core.spec.id, name: core.spec.kind, position: core.position, rotation: core.rotation, body: core.body, spec: core.describe() }),\n reset: core.resetBody,\n})\n","import type { Quat, Vec3 } from '@adatechnology/game-contracts'\n\n/** `v` rotated by the unit quaternion `q`. */\nexport const rotate = (q: Quat, v: Vec3): Vec3 => {\n const [x, y, z, w] = q\n const tx = 2 * (y * v[2] - z * v[1])\n const ty = 2 * (z * v[0] - x * v[2])\n const tz = 2 * (x * v[1] - y * v[0])\n return [v[0] + w * tx + (y * tz - z * ty), v[1] + w * ty + (z * tx - x * tz), v[2] + w * tz + (x * ty - y * tx)]\n}\n\nconst conjugate = (q: Quat): Quat => [-q[0], -q[1], -q[2], q[3]]\n\nexport type Transform = { readonly position: Vec3; readonly rotation: Quat }\n\nexport const toWorld = ({ position, rotation }: Transform, local: Vec3): Vec3 => {\n const turned = rotate(rotation, local)\n return [turned[0] + position[0], turned[1] + position[1], turned[2] + position[2]]\n}\n\nexport const toLocal = ({ position, rotation }: Transform, world: Vec3): Vec3 => rotate(conjugate(rotation), [world[0] - position[0], world[1] - position[1], world[2] - position[2]])\n\nexport const distance = (a: Vec3, b: Vec3): number => Math.hypot(a[0] - b[0], a[1] - b[1], a[2] - b[2])\n","import type { DestructionEvent, Vec3 } from '@adatechnology/game-contracts'\n\nimport type { SegmentId } from '../body/segment-tree'\n\n/** A bleeding wound: `rate` in drops per second (the Arsenal's unit) fading to 0 over `duration` seconds; `spurt` pulses like an artery. */\nexport type Bleeder = {\n readonly part: SegmentId\n readonly rate: number\n readonly duration: number\n readonly spurt: boolean\n age: number\n /** Whole seconds of this bleeder already reported as `leak` events. */\n reported: number\n}\n\n/** Volume of one drop (a 4 mm drop of the Arsenal's blood): `leak` events carry litres per second. */\nexport const BLOOD_LITERS_PER_DROP = 0.00027\n\nexport const bleedRateAt = (bleeder: Bleeder): number => (bleeder.age >= bleeder.duration ? 0 : bleeder.rate * (1 - bleeder.age / bleeder.duration))\n\nexport type StepBleedingParams = {\n readonly bleeders: Bleeder[]\n readonly dt: number\n readonly emit: (event: Omit<Extract<DestructionEvent, { type: 'leak' }>, 'object' | 'time'>) => void\n readonly pointOf: (id: SegmentId) => Vec3\n}\n\n/** Ages the bleeders; each one still running reports a `leak` with its current rate once per second of its life. */\nexport const stepBleeding = ({ bleeders, dt, emit, pointOf }: StepBleedingParams): void => {\n for (const bleeder of bleeders) {\n if (bleeder.age >= bleeder.duration) continue\n bleeder.age += dt\n const second = Math.floor(bleeder.age)\n if (second <= bleeder.reported) continue\n bleeder.reported = second\n const rate = bleedRateAt(bleeder)\n if (rate > 0) emit({ type: 'leak', part: bleeder.part, fluid: 'blood', point: pointOf(bleeder.part), direction: [0, -1, 0], rate: rate * BLOOD_LITERS_PER_DROP, pressurized: bleeder.spurt })\n }\n}\n","import type { DamageType, DestructionEvent, Vec3 } from '@adatechnology/game-contracts'\n\nimport type { BodyState } from '../body/body-state'\nimport { segmentOf } from '../body/body-state'\nimport { segmentNode, segmentsBelow } from '../body/segment-tree'\nimport type { SegmentId, SegmentSide } from '../body/segment-tree'\nimport type { ResolvedCharacterSpec } from '../character'\nimport type { SegmentState } from '../types'\nimport { BLOOD_LITERS_PER_DROP } from './bleeding'\nimport type { Bleeder } from './bleeding'\nimport type { DamageRules, DeathRule } from './types'\n\ntype BodyChange = Extract<DestructionEvent, { type: 'body' }>['change']\ntype KillCause = 'head' | 'vitality' | 'bleed' | 'explosion'\ntype EventDraft = DestructionEvent extends infer E ? (E extends DestructionEvent ? Omit<E, 'object' | 'time'> : never) : never\n\nexport type BleedParams = { readonly segment: SegmentState; readonly rate: number; readonly duration: number; readonly spurt: boolean; readonly point?: Vec3; readonly direction?: Vec3 }\n\n/** How severing treats what hangs below: the Arsenal only detaches it, the Elenco also zeroes it and marks it cut. */\nexport type SeverBelow = 'detach' | 'zero'\n\n/** Every change a damage rule can make to a body, each emitting its events. The rules (kit, arsenal, elenco, regions) only decide. */\nexport type BodyOps = {\n readonly body: BodyState\n readonly spec: ResolvedCharacterSpec\n readonly rules: DamageRules\n readonly random: () => number\n readonly events: DestructionEvent[]\n emit(event: EventDraft): void\n pointOf(id: SegmentId): Vec3\n change(change: BodyChange, part?: SegmentId, extra?: { cause?: KillCause; below?: string[] }): void\n damage(segment: SegmentState, amount: number, damageType: DamageType): void\n wound(segment: SegmentState): void\n breakBone(segment: SegmentState): void\n sever(segment: SegmentState, below?: SeverBelow): void\n destroy(segment: SegmentState): void\n kill(cause: KillCause): void\n limp(side: SegmentSide): void\n crawl(): void\n /** A heavy hit staggers the body for the spec's `stunSeconds`. */\n stun(): void\n bleed(params: BleedParams): void\n}\n\nexport type CreateBodyOpsParams = {\n readonly body: BodyState\n readonly spec: ResolvedCharacterSpec\n readonly rules: DamageRules\n readonly random: () => number\n readonly time: number\n readonly source?: string\n readonly pointOf: (id: SegmentId) => Vec3\n readonly bleeders: Bleeder[]\n}\n\nconst killAllowed = (rule: DeathRule, cause: KillCause): boolean => rule === 'vitality-or-head' || cause === 'head' || cause === 'explosion'\n\nexport const createBodyOps = ({ body, spec, rules, random, time, source, pointOf, bleeders }: CreateBodyOpsParams): BodyOps => {\n const events: DestructionEvent[] = []\n const emit = (event: EventDraft): void => void events.push({ ...event, object: spec.id, time, ...(source !== undefined ? { source } : {}) } as DestructionEvent)\n const change: BodyOps['change'] = (kind, part, extra) => emit({ type: 'body', change: kind, ...(part ? { part } : {}), ...extra })\n const detachBelow = (segment: SegmentState, below: SeverBelow): SegmentId[] => {\n const fallen = segmentsBelow(segment.id).filter((id) => segmentOf(body, id).attached)\n segment.attached = false\n for (const id of fallen) {\n const part = segmentOf(body, id)\n part.attached = false\n if (below === 'zero') Object.assign(part, { hp: 0, status: 'severed' })\n }\n return fallen\n }\n const ops: BodyOps = {\n body,\n spec,\n rules,\n random,\n events,\n emit,\n pointOf,\n change,\n damage: (segment, amount, damageType) => emit({ type: 'damage', part: segment.id, amount, hp: Math.max(0, segment.hp), damageType }),\n wound(segment) {\n if (segment.status === 'ok') segment.status = 'wounded'\n change('wound', segment.id)\n },\n breakBone(segment) {\n segment.status = 'broken'\n change('broken', segment.id)\n },\n sever(segment, below = 'detach') {\n if (!segment.attached) return\n const fallen = detachBelow(segment, below)\n segment.status = 'severed'\n body.pieces.push([segment.id, ...fallen])\n const parent = segmentNode(segment.id).parent\n change('severed', segment.id, { below: fallen })\n if (parent) emit({ type: 'detach', joint: `${parent}~${segment.id}`, parts: [parent, segment.id], by: 'break', groups: [[segment.id, ...fallen]] })\n },\n destroy(segment) {\n if (!segment.attached) return\n const fallen = detachBelow(segment, 'detach')\n segment.status = 'destroyed'\n if (fallen.length > 0) body.pieces.push(fallen)\n change('destroyed', segment.id, { below: fallen })\n emit({ type: 'fracture', part: segment.id, style: 'tear', fragments: [], point: pointOf(segment.id) })\n },\n kill(cause) {\n if (!body.alive || !killAllowed(rules.deathRule, cause)) return\n body.alive = false\n change('killed', undefined, { cause })\n },\n limp(side) {\n if (body.limping.includes(side)) return\n body.limping.push(side)\n change('limp')\n },\n crawl() {\n if (body.crawl) return\n body.crawl = true\n change('crawl')\n },\n stun() {\n body.stunSeconds = spec.stunSeconds\n change('stunned')\n },\n bleed({ segment, rate, duration, spurt, point, direction }) {\n const scaled = rate * spec.bloodFactor\n bleeders.push({ part: segment.id, rate: scaled, duration, spurt, age: 0, reported: 0 })\n emit({ type: 'leak', part: segment.id, fluid: 'blood', point: point ?? pointOf(segment.id), direction: direction ?? [0, -1, 0], rate: scaled * BLOOD_LITERS_PER_DROP, pressurized: spurt })\n },\n }\n return ops\n}\n","{\n \"id\": \"physical\",\n \"tissuePerCentimetre\": {\n \"flesh\": 0.25,\n \"bone\": 1\n },\n \"torsoPath\": {\n \"fleshCentimetres\": 22,\n \"boneCentimetres\": 2\n },\n \"regionFactor\": {\n \"head\": 0.7,\n \"limb\": 0.5,\n \"torso\": 1\n },\n \"bruteTorsoFactor\": 2,\n \"energyKept\": \"P / (P + R)\",\n \"points\": {\n \"coefficient\": 3.5,\n \"exponent\": 0.37\n },\n \"tolerance\": {\n \"bodies\": 0,\n \"energyKept\": 0.05\n },\n \"calibration\": [\n {\n \"caliber\": \"9x19\",\n \"force\": 7.67,\n \"bodies\": 2,\n \"energyKeptFirstBody\": 0.51,\n \"expectedBodies\": 2,\n \"bestiaryEnergyKept\": 0.5\n },\n {\n \"caliber\": \"5_56x45\",\n \"force\": 16.56,\n \"bodies\": 3,\n \"energyKeptFirstBody\": 0.69,\n \"expectedBodies\": 3,\n \"bestiaryEnergyKept\": 0.65\n },\n {\n \"caliber\": \"7_62x51\",\n \"force\": 26.67,\n \"bodies\": 4,\n \"energyKeptFirstBody\": 0.78,\n \"expectedBodies\": 4,\n \"bestiaryEnergyKept\": 0.75\n },\n {\n \"caliber\": \"7_62x39\",\n \"force\": 18.52,\n \"bodies\": 3,\n \"energyKeptFirstBody\": 0.71,\n \"expectedBodies\": 3\n },\n {\n \"caliber\": \"12ga_00buck\",\n \"force\": 4.35,\n \"bodies\": 1,\n \"energyKeptFirstBody\": 0.37,\n \"expectedBodies\": 1\n }\n ],\n \"torsoResistance\": 7.5\n}\n","import type { SegmentKind } from '@adatechnology/game-contracts'\n\nimport { SEGMENT_NUMBERS } from '../body/segment-tree'\nimport segments from '../data/segments.json'\nimport physical from '../presets/physical.json'\nimport teamGame from '../presets/team-game.json'\nimport type { BallisticClass, CaliberEntry, DamageRules, ProtectionLayer } from './types'\n\nconst { severity } = segments\n\n/** The kit's rules: Arsenal numbers per segment (A4), the design's severity, the game's head rule, death by vitality or head. */\nexport const DEFAULT_DAMAGE_RULES: DamageRules = {\n deathRule: 'vitality-or-head',\n segmentRule: 'kit',\n severity: { ...severity, stunAtPoints: 35, limbVitalityShare: 0.3, regionLimbVitalityShare: 0.5 },\n blast: { minimumPoints: 8, headDestroyPoints: 40, bigPoints: 120 },\n defaultCut: segments.defaultCut,\n points: physical.points,\n spread: 0,\n segments: SEGMENT_NUMBERS,\n burnPointsPerSecond: 3,\n}\n\n/** The Galeria 3D do Arsenal, replayed: its `damage`, `sever`, `explodeSeg`, `splitTorso`, `legLost` and `grenadeAt`. */\nexport const ARSENAL_RULES: DamageRules = { ...DEFAULT_DAMAGE_RULES, segmentRule: 'arsenal' }\n\nconst ELENCO_HIT_POINTS = segments.elenco.segments as Partial<Record<SegmentKind, { readonly hp: number }>>\n\n/** The Elenco, replayed: its own hit points, no multiplier, ±15 % per blow and its cut rule (`hit`, `sever`, `breakBone`); a torso at 0 kills (a human). */\nexport const ELENCO_RULES: DamageRules = {\n ...DEFAULT_DAMAGE_RULES,\n segmentRule: 'elenco',\n spread: 0.15,\n segments: Object.fromEntries(\n Object.entries(SEGMENT_NUMBERS).map(([kind, numbers]) => [kind, { ...numbers, multiplier: 1, hitPoints: ELENCO_HIT_POINTS[kind as SegmentKind]?.hp ?? numbers.hitPoints }]),\n ) as DamageRules['segments'],\n}\n\nexport const DAMAGE_PRESETS = { kit: DEFAULT_DAMAGE_RULES, arsenal: ARSENAL_RULES, elenco: ELENCO_RULES } as const\n\n/** The protection presets that reproduce the game's `ROUPAS` (tools/characters-catalog/decisions.json `protectionPresets`). */\nexport const PROTECTION_PRESETS: readonly ProtectionLayer[] = [\n { id: 'vest_police', slots: ['torso'], ballistic: { resistance: 14, blunt: 0.3, pass: 0.8 } },\n { id: 'vest_military', slots: ['torso'], ballistic: { resistance: 28, blunt: 0.5 } },\n { id: 'helmet_combat', slots: ['head'], ballistic: { resistance: 9, blunt: 0, pass: 1, consumable: true } },\n { id: 'turnout_gear', slots: ['torso', 'arms', 'legs'], fire: 0.25, limbs: 0.8 },\n]\n\nconst CLASS_OF: Readonly<Record<string, BallisticClass>> = { pistol: 'pistol', rifle: 'rifle' }\n\n/** The game's calibre table (`CALIBRES`) under the kit's calibre ids, for the `team-game` model. */\nexport const TEAM_GAME_CALIBERS: readonly CaliberEntry[] = Object.entries(teamGame.calibers).map(([id, entry]) => ({\n id,\n points: entry.points,\n penetration: entry.penetration,\n class: CLASS_OF[entry.class] ?? 'pistol',\n skullRange: entry.skullRange,\n pellets: 'pellets' in entry ? entry.pellets : 1,\n effectiveRangeMetres: entry.effectiveRangeMetres,\n}))\n\n/** The game's calibre keys (`9x19`, `12ga`, `762x39`, `308`) to the kit's calibre ids. */\nexport const TEAM_GAME_CALIBER_KEYS: Readonly<Record<string, string>> = Object.fromEntries(Object.entries(teamGame.calibers).map(([id, entry]) => [entry.gameKey, id]))\n\nexport const TEAM_GAME_RULES = { regionCost: teamGame.regionCost, damageKeptPerBody: teamGame.damageKeptPerBody, falloff: teamGame.falloff } as const\n\nexport const PHYSICAL_RULES = physical\n","import type { BodyRegion, SegmentKind } from '@adatechnology/game-contracts'\n\nimport { PHYSICAL_RULES, TEAM_GAME_RULES } from './defaults'\nimport type { PenetrationModel } from './types'\n\n/** P = √(E·m/A) against the resistance of the path; a protection layer stops a projectile whose force is not above its resistance. */\nexport const PHYSICAL_PENETRATION: PenetrationModel = {\n id: 'physical',\n stops: (layer, projectile) => projectile.force <= (layer.ballistic?.resistance ?? 0),\n piercesSkull: (projectile, headResistance) => projectile.force > headResistance,\n}\n\n/** The game's rule: pistol-class rounds are stopped by a vest or a helmet; the skull is pierced within the calibre's `cranio` range. */\nexport const TEAM_GAME_PENETRATION: PenetrationModel = {\n id: 'team-game',\n stops: (_layer, projectile) => projectile.class === 'pistol',\n piercesSkull: (projectile) => projectile.skullRange === 1 || projectile.distance <= projectile.skullRange,\n}\n\nexport const PENETRATION_MODELS = { physical: PHYSICAL_PENETRATION, 'team-game': TEAM_GAME_PENETRATION } as const\n\nconst { tissuePerCentimetre, torsoPath, regionFactor } = PHYSICAL_RULES\n\n/** Resistance of a torso path: flesh 22 cm × 0.25 + bone 2 cm × 1.0 = 7.5. */\nexport const TORSO_RESISTANCE = torsoPath.fleshCentimetres * tissuePerCentimetre.flesh + torsoPath.boneCentimetres * tissuePerCentimetre.bone\n\nconst HEAD_KINDS: ReadonlySet<SegmentKind> = new Set(['head', 'jaw', 'neck'])\nconst TORSO_KINDS: ReadonlySet<SegmentKind> = new Set(['torso', 'pelvis'])\n\nexport type ResistanceParams = { readonly kind: SegmentKind; readonly bodyCount: number; readonly protection: number }\n\n/** R of the path through a segment: torso 7.5 (× the body count of a brute), head 0.7×, limbs 0.5×, plus the protection worn over it. */\nexport const segmentResistance = ({ kind, bodyCount, protection }: ResistanceParams): number => {\n if (TORSO_KINDS.has(kind)) return TORSO_RESISTANCE * regionFactor.torso * bodyCount + protection\n if (HEAD_KINDS.has(kind)) return TORSO_RESISTANCE * regionFactor.head + protection\n return TORSO_RESISTANCE * regionFactor.limb + protection\n}\n\n/** Share of the energy a projectile of force `force` keeps after a path of resistance `resistance`: P/(P+R). */\nexport const energyKept = (force: number, resistance: number): number => (force > 0 ? force / (force + resistance) : 0)\n\n/** Penetration points a region costs in the game (`custo`): head 0.7, torso 1 (a brute 2), limb 0.5. */\nexport const teamGameCost = (region: BodyRegion, bodyCount: number): number => {\n const cost = TEAM_GAME_RULES.regionCost\n if (region === 'head') return cost.head\n if (region === 'torso') return bodyCount > 1 ? cost.bruteTorso : cost.torso\n return cost.limb\n}\n\n/** The game's falloff: full damage up to the effective range, then linear down to half at twice the range, never below half. */\nexport const teamGameFalloff = (distance: number, range: number): number => {\n const floor = TEAM_GAME_RULES.falloff.atTwiceRange\n return distance <= range * TEAM_GAME_RULES.falloff.fullAtRange ? 1 : Math.max(floor, 1 - ((distance - range) / range) * (1 - floor))\n}\n","import type { DamageType, SegmentKind, Vec3 } from '@adatechnology/game-contracts'\n\nimport { segmentNode } from '../../body/segment-tree'\nimport type { ResolvedCharacterSpec } from '../../character'\nimport type { SegmentState } from '../../types'\nimport type { BodyOps } from '../body-ops'\nimport type { PenetrationModel, ProjectileInfo } from '../types'\n\n/** One blow on one segment, after protection: what every segment rule receives. */\nexport type SegmentBlow = {\n readonly segment: SegmentState\n /** Points after protection, before the rule's multipliers and spread. */\n readonly points: number\n readonly cut: number\n readonly damageType: DamageType\n readonly projectile?: ProjectileInfo\n readonly explosive: boolean\n /** A blast strong enough to destroy what it takes to 0 (Arsenal `big`). */\n readonly big: boolean\n /** Where it landed (world): a bullet wound bleeds there; a blast share has none. */\n readonly point?: Vec3\n /** Extra factor on arms and legs (age × protection). */\n readonly limbFactor: number\n readonly model: PenetrationModel\n /** Resistance of the head path (the skull rule of the `physical` model). */\n readonly headResistance: number\n}\n\nexport type RuleResult = { readonly headshot: boolean }\n\nexport type SegmentRule = (ops: BodyOps, blow: SegmentBlow) => RuleResult\n\nexport const NO_HEADSHOT: RuleResult = { headshot: false }\nexport const HEADSHOT: RuleResult = { headshot: true }\n\nconst ARM_KINDS: ReadonlySet<SegmentKind> = new Set(['upperArm', 'forearm', 'hand'])\nconst LEG_KINDS: ReadonlySet<SegmentKind> = new Set(['thigh', 'shin', 'foot'])\n\nexport const isArm = (kind: SegmentKind): boolean => ARM_KINDS.has(kind)\nexport const isLeg = (kind: SegmentKind): boolean => LEG_KINDS.has(kind)\nexport const isLimb = (kind: SegmentKind): boolean => isArm(kind) || isLeg(kind)\n\n/** The body type's multiplier for the group the segment is in (head, torso, arms, legs). */\nexport const typeMultiplier = (spec: ResolvedCharacterSpec, kind: SegmentKind): number => {\n if (isArm(kind)) return spec.multipliers.arms\n if (isLeg(kind)) return spec.multipliers.legs\n if (kind === 'torso' || kind === 'pelvis') return spec.multipliers.torso\n return spec.multipliers.head\n}\n\n/** Points the segment takes: the blow × segment multiplier × body type × (on a limb) age and protection. */\nexport const segmentDamage = (ops: BodyOps, blow: SegmentBlow, points: number): number => {\n const { kind } = blow.segment\n return points * ops.rules.segments[kind].multiplier * typeMultiplier(ops.spec, kind) * (isLimb(kind) ? blow.limbFactor : 1)\n}\n\n/** The stump a lost segment leaves bleeds hard (×1.5 at the neck and head) for 45 s, spurting (Arsenal `stumpAt`). */\nexport const bleedStump = (ops: BodyOps, segment: SegmentState): void => {\n const bleed = ops.rules.segments[segment.kind].bleed\n const parent = segmentNode(segment.id).parent\n const stump = parent ? (ops.body.segments.find((candidate) => candidate.id === parent) ?? segment) : segment\n ops.bleed({ segment: stump, rate: bleed * (segment.kind === 'neck' || segment.kind === 'head' ? 1.5 : 1), duration: 45, spurt: true })\n}\n\n/** The piece that flies off bleeds 35 % of the rate for 15 s (Arsenal `sever`). */\nexport const bleedPiece = (ops: BodyOps, segment: SegmentState): void => ops.bleed({ segment, rate: ops.rules.segments[segment.kind].bleed * 0.35, duration: 15, spurt: true })\n\n/** A bullet wound bleeds 30 % of the segment's rate for 10 s, without spurting (Arsenal `damage` with a point). */\nexport const bleedWound = (ops: BodyOps, segment: SegmentState, point: Vec3): void =>\n ops.bleed({ segment, rate: ops.rules.segments[segment.kind].bleed * 0.3, duration: 10, spurt: false, point })\n\n/** Cut off at the joint, with its two bleeders. */\nexport const severWithBleeding = (ops: BodyOps, segment: SegmentState): void => {\n if (!segment.attached) return\n bleedStump(ops, segment)\n ops.sever(segment)\n bleedPiece(ops, segment)\n}\n\n/** Blown to pieces: only the stump bleeds. */\nexport const destroyWithBleeding = (ops: BodyOps, segment: SegmentState): void => {\n if (!segment.attached) return\n bleedStump(ops, segment)\n ops.destroy(segment)\n}\n","import { MISSING_BITS } from '@adatechnology/game-contracts'\nimport type { BodyRegion, DamageType } from '@adatechnology/game-contracts'\n\nimport { segmentOf } from '../../body/body-state'\nimport { REGION_HIT_POINTS, REGION_SEGMENTS } from '../../body/regions'\nimport type { LimbRegion } from '../../body/regions'\nimport type { BodyOps } from '../body-ops'\nimport { spreadPoints } from '../points'\nimport type { ProtectionOutcome } from '../protection'\nimport type { PenetrationModel, ProjectileInfo } from '../types'\nimport { HEADSHOT, NO_HEADSHOT } from './blow'\nimport type { RuleResult } from './blow'\n\n/** One blow on one crowd region. `points` are the blow's own (the game stuns on them); the torso applies the vest share itself. */\nexport type RegionBlow = {\n readonly region: BodyRegion\n readonly points: number\n readonly cut: number\n readonly damageType: DamageType\n readonly projectile?: ProjectileInfo\n readonly protection: ProtectionOutcome\n readonly model: PenetrationModel\n readonly headResistance: number\n}\n\nconst LIMB_BITS: Readonly<Record<Exclude<LimbRegion, 'head'>, { readonly severed: number; readonly broken: number }>> = {\n armL: { severed: MISSING_BITS.armL, broken: MISSING_BITS.armLBroken },\n armR: { severed: MISSING_BITS.armR, broken: MISSING_BITS.armRBroken },\n legL: { severed: MISSING_BITS.legL, broken: MISSING_BITS.legLBroken },\n legR: { severed: MISSING_BITS.legR, broken: MISSING_BITS.legRBroken },\n}\n\nconst rootOf = (ops: BodyOps, region: BodyRegion) => segmentOf(ops.body, REGION_SEGMENTS[region][0] as Parameters<typeof segmentOf>[1])\n\nconst hitHead = (ops: BodyOps, blow: RegionBlow, points: number): RuleResult => {\n const { body, rules } = ops\n const rule = rules.severity\n const multiplier = rules.segments.head.multiplier\n const { projectile } = blow\n const lethal = projectile ? blow.model.piercesSkull(projectile, blow.headResistance) && points >= rule.headKillDamage : points * multiplier >= body.regions.head\n if (lethal) {\n const shotgunClose = projectile !== undefined && projectile.pellets > 1 && projectile.distance < rule.headBitShotgunMetres\n if (points > rule.headBitDamage || shotgunClose) {\n body.missing |= MISSING_BITS.head\n ops.destroy(segmentOf(body, 'head'))\n }\n return HEADSHOT\n }\n body.vitality -= points * multiplier\n body.regions.head -= points\n ops.damage(segmentOf(body, 'head'), points * multiplier, blow.damageType)\n if (points > rule.jawDamage && ops.random() < rule.jawChance && (body.missing & MISSING_BITS.jaw) === 0) {\n body.missing |= MISSING_BITS.jaw\n ops.sever(segmentOf(body, 'jaw'))\n }\n return NO_HEADSHOT\n}\n\nconst hitLimb = (ops: BodyOps, blow: RegionBlow, region: Exclude<LimbRegion, 'head'>, points: number): void => {\n const { body, spec, rules } = ops\n const leg = region === 'legL' || region === 'legR'\n const factor = (leg ? spec.multipliers.legs : spec.multipliers.arms) * spec.limbFactor * blow.protection.limbs\n const amount = points * factor\n body.regions[region] -= amount\n body.vitality -= amount * rules.severity.regionLimbVitalityShare\n const root = rootOf(ops, region)\n ops.damage(root, amount, blow.damageType)\n const max = REGION_HIT_POINTS[region]\n if (leg && body.regions[region] <= max * rules.severity.limpAtHpFraction) ops.limp(region === 'legL' ? 'L' : 'R')\n if (body.regions[region] > 0) return\n const severs = blow.cut >= rules.severity.severAtCut || amount > max * rules.severity.severAtDamageFraction\n const bit = severs ? LIMB_BITS[region].severed : LIMB_BITS[region].broken\n const isNew = (body.missing & bit) === 0\n body.missing |= bit\n if (leg) ops.crawl()\n if (!isNew) return\n if (severs) ops.sever(root)\n else ops.breakBone(root)\n}\n\n/** The game's `zDamage` (G 67011–67045): the crowd model of 6 regions, the bitmask, the helmet, the vest, limp, crawl and the jaw. */\nexport const regionRule = (ops: BodyOps, blow: RegionBlow): RuleResult => {\n const { body, rules } = ops\n const points = spreadPoints(blow.points, rules.spread, ops.random)\n let result = NO_HEADSHOT\n if (blow.region === 'head') result = hitHead(ops, blow, points)\n else if (blow.region === 'torso') {\n const amount = points * ops.spec.multipliers.torso * blow.protection.ballistic\n body.vitality -= amount\n ops.damage(segmentOf(body, 'torso'), amount, blow.damageType)\n } else hitLimb(ops, blow, blow.region, points)\n if (result.headshot) ops.kill('head')\n else if (body.vitality <= 0) ops.kill('vitality')\n if (!body.alive || result.headshot || body.vitality <= 0) return result\n if (points >= rules.severity.stunAtPoints) ops.stun()\n return result\n}\n","import type { DamageType } from '@adatechnology/game-contracts'\n\nimport type { BallisticClass, BodyHit, CaliberEntry, DamageRules, ProjectileInfo } from './types'\n\n/** Deterministic mulberry32 stream in [0, 1). */\nexport const createRng = (seed: number): (() => number) => {\n let state = seed >>> 0\n return () => {\n state = (state + 0x6d2b79f5) >>> 0\n let mixed = Math.imul(state ^ (state >>> 15), state | 1)\n mixed ^= mixed + Math.imul(mixed ^ (mixed >>> 7), mixed | 61)\n return ((mixed ^ (mixed >>> 14)) >>> 0) / 4294967296\n }\n}\n\n/** Damage points of a blow from its energy in joules: `coefficient · E^exponent` (9×19 → 35, 7.62×39 → 59, .308 → 71.7). */\nexport const pointsFromEnergy = (energy: number, rules: Pick<DamageRules, 'points'>): number => (energy > 0 ? rules.points.coefficient * energy ** rules.points.exponent : 0)\n\n/** The caller's points, else the calibre table's, else the energy formula. */\nexport const resolvePoints = (hit: BodyHit, caliber: CaliberEntry | undefined, rules: Pick<DamageRules, 'points'>): number => hit.points ?? caliber?.points ?? pointsFromEnergy(hit.energy ?? 0, rules)\n\n/** One draw of ±`spread` on the points (none when the spread is 0, so the stream is not touched). */\nexport const spreadPoints = (points: number, spread: number, random: () => number): number => (spread > 0 ? points * (1 - spread + random() * 2 * spread) : points)\n\nconst DEFAULT_PROJECTILE_GRAMS = 8\nconst RIFLE_JOULES = 1000\n\n/** P = √(E·m/A): E in joules, m in grams, A the cross-section in mm². */\nexport const penetrationForce = (energy: number, grams: number, diameterMm: number): number => {\n const area = (Math.PI * diameterMm ** 2) / 4\n return area > 0 && energy > 0 ? Math.sqrt((energy * grams) / area) : 0\n}\n\n/** What a ballistic hit is (force, class, skull range, pellets, distance), from the hit and the calibre table. */\nexport const projectileOf = (hit: BodyHit, caliber: CaliberEntry | undefined): ProjectileInfo => {\n const pellets = hit.pellets ?? caliber?.pellets ?? 1\n const energy = hit.energy ?? 0\n const fallback: BallisticClass = energy > RIFLE_JOULES ? 'rifle' : 'pistol'\n return {\n force: penetrationForce(energy, hit.mass ?? DEFAULT_PROJECTILE_GRAMS, hit.caliber ?? 9),\n class: caliber?.class ?? fallback,\n skullRange: caliber?.skullRange ?? 1,\n pellets,\n distance: hit.distance ?? 0,\n }\n}\n\n/** `hit.cut`, else the default of its damage type (a bullet by class: pistol 0.15, buckshot 0.75, rifle 0.45). */\nexport const cutOf = (hit: BodyHit, projectile: ProjectileInfo | undefined, rules: Pick<DamageRules, 'defaultCut'>): number => {\n if (hit.cut !== undefined) return hit.cut\n const type: DamageType = hit.type\n if (type === 'ballistic' && projectile) return rules.defaultCut.ballistic[projectile.pellets > 1 ? 'buckshot' : projectile.class]\n if (type === 'slash' || type === 'blunt' || type === 'explosive') return rules.defaultCut[type]\n return 0\n}\n","import type { Vec3 } from '@adatechnology/game-contracts'\n\nimport { REGION_SEGMENTS, BODY_REGIONS } from '../body/regions'\nimport { segmentNode } from '../body/segment-tree'\nimport type { SegmentId } from '../body/segment-tree'\nimport { distance } from '../body/transform'\nimport type { BodyOps } from './body-ops'\nimport { HEADSHOT, NO_HEADSHOT, destroyWithBleeding } from './rules/blow'\nimport type { RuleResult, SegmentBlow, SegmentRule } from './rules/blow'\nimport { regionRule } from './rules/regions'\nimport type { RegionBlow } from './rules/regions'\n\nexport type BlastParams = {\n readonly ops: BodyOps\n /** Centre of the blast in the body's local space. */\n readonly center: Vec3\n readonly points: number\n readonly radius: number\n /** Inside this distance a segment takes the whole blast (lethal); from it to `radius` it takes at most `blast.injuryPoints`, falling off to nothing at `radius`. Without it: `points × (1 − distance/radius)`. */\n readonly lethalRadius?: number\n /** A joint position in local space. */\n readonly jointOf: (id: SegmentId) => Vec3\n}\n\n/** Points per segment at the edge of the lethal radius when the rules name none: a person there is left badly hurt, not dead. */\nconst INJURY_POINTS = 15\n\n/** The points of a blast on a segment `metres` from its centre: `points × (1 − distance/radius)`; with a `lethalRadius`, all of them inside it and, beyond it, the injury share that falls off to the edge. */\nconst pointsAt = (params: BlastParams, metres: number): number => {\n const { points, radius, lethalRadius, ops } = params\n if (lethalRadius === undefined || lethalRadius >= radius) return points * Math.max(0, 1 - metres / radius)\n if (metres <= lethalRadius) return points\n const injury = Math.min(points, ops.rules.blast.injuryPoints ?? INJURY_POINTS)\n return injury * Math.max(0, 1 - (metres - lethalRadius) / (radius - lethalRadius))\n}\n\n/** The share of a blast each target takes (`pointsAt`), kept above the minimum, strongest first (Arsenal `grenadeAt`). */\nconst shares = <TTarget>(params: BlastParams, targets: readonly TTarget[], pivot: (target: TTarget) => SegmentId): { target: TTarget; points: number }[] =>\n targets\n .map((target) => ({ target, points: pointsAt(params, distance(params.jointOf(pivot(target)), params.center)) }))\n .filter((share) => share.points > params.ops.rules.blast.minimumPoints)\n .sort((a, b) => b.points - a.points)\n\nexport type SegmentBlastParams = BlastParams & { readonly rule: SegmentRule; readonly blow: Omit<SegmentBlow, 'segment' | 'points' | 'big' | 'explosive' | 'point'> }\n\n/** A blast on the 17 segments: a strong share on the head blows it off; every other share goes through the segment rule as an explosive blow. */\nexport const segmentBlast = (params: SegmentBlastParams): RuleResult => {\n const { ops, rule, blow } = params\n const { blast, segments } = ops.rules\n let result = NO_HEADSHOT\n for (const { target, points } of shares(params, ops.body.segments.filter((segment) => segment.attached), (segment) => segment.id)) {\n if (!target.attached) continue\n if (target.kind === 'head' && points > blast.headDestroyPoints) {\n destroyWithBleeding(ops, target)\n ops.kill('explosion')\n result = HEADSHOT\n continue\n }\n rule(ops, { ...blow, segment: target, points: points / segments[target.kind].multiplier, big: points > blast.bigPoints, explosive: true })\n }\n return result\n}\n\nexport type RegionBlastParams = BlastParams & { readonly blow: Omit<RegionBlow, 'region' | 'points'> }\n\n/** A blast on the 6 crowd regions, each measured at the joint of the segment that names it. */\nexport const regionBlast = (params: RegionBlastParams): RuleResult => {\n let result = NO_HEADSHOT\n const pivot = (region: (typeof BODY_REGIONS)[number]): SegmentId => segmentNode(REGION_SEGMENTS[region][0] as SegmentId).id\n for (const { target, points } of shares(params, BODY_REGIONS, pivot)) {\n if (regionRule(params.ops, { ...params.blow, region: target, points }).headshot) result = HEADSHOT\n }\n return result\n}\n","import type { BodySlot } from '@adatechnology/game-contracts'\n\nimport type { PenetrationModel, ProjectileInfo, ProtectionLayer } from './types'\n\n/** The layered protection of T3: `1 − Π(1 − value·condition)`, at most `cap`. */\nexport const LAYERED_PROTECTION_CAP = 0.9\n\nexport type LayeredProtectionParams = {\n readonly layers: readonly ProtectionLayer[]\n readonly attack: 'bite' | 'scratch'\n /** 0..1 condition per layer id (worn, torn); 1 by default. */\n readonly conditions?: Readonly<Record<string, number>>\n}\n\nexport const layeredProtection = ({ layers, attack, conditions }: LayeredProtectionParams): number => {\n const through = layers.reduce((left, layer) => left * (1 - (layer[attack] ?? 0) * (conditions?.[layer.id] ?? 1)), 1)\n return Math.min(LAYERED_PROTECTION_CAP, 1 - through)\n}\n\n/** The layers worn that cover any of `slots` and are not used up. */\nexport const layersOn = (worn: readonly ProtectionLayer[], slots: readonly BodySlot[], consumed: ReadonlySet<string>): ProtectionLayer[] =>\n worn.filter((layer) => !consumed.has(layer.id) && layer.slots.some((slot) => slots.includes(slot)))\n\n/** What the layers over a segment do to one blow. */\nexport type ProtectionOutcome = {\n /** A consumable layer took the whole projectile (a helmet): no damage, and the layer is used up. */\n readonly absorbedBy?: string\n /** Share of the points that gets through the ballistic layers. */\n readonly ballistic: number\n /** Penetration resistance the layers add (the `physical` model). */\n readonly resistance: number\n /** Factor on limb damage (a turnout coat). */\n readonly limbs: number\n /** Factor on fire damage. */\n readonly fire: number\n}\n\nexport type ProtectParams = {\n readonly layers: readonly ProtectionLayer[]\n readonly projectile?: ProjectileInfo\n readonly model: PenetrationModel\n}\n\n/** A stopped projectile does the layer's `blunt` share; one that goes through, `pass` (default `blunt`). Non-projectiles ignore ballistic layers. */\nexport const protect = ({ layers, projectile, model }: ProtectParams): ProtectionOutcome => {\n let ballistic = 1\n let resistance = 0\n for (const layer of layers) {\n const armour = layer.ballistic\n if (!armour || !projectile) continue\n const stops = model.stops(layer, projectile)\n if (stops && armour.consumable) return { absorbedBy: layer.id, ballistic: 0, resistance: armour.resistance, limbs: 1, fire: 1 }\n ballistic *= stops ? armour.blunt : (armour.pass ?? armour.blunt)\n resistance += armour.resistance\n }\n const limbs = layers.reduce((factor, layer) => factor * (layer.limbs ?? 1), 1)\n const fire = layers.reduce((factor, layer) => factor * (layer.fire ?? 1), 1)\n return { ballistic, resistance, limbs, fire }\n}\n","import type { BodyRegion, DestructibleSpec, Vec3 } from '@adatechnology/game-contracts'\n\nimport type { BodyState } from '../body/body-state'\nimport { isBodyRegion, REGION_SEGMENTS } from '../body/regions'\nimport { isSegmentId } from '../body/segment-tree'\nimport type { SegmentId } from '../body/segment-tree'\nimport { distance } from '../body/transform'\n\nconst radiusOf = (part: DestructibleSpec['parts'][number]): number => (part.shape.kind === 'box' ? Math.min(...part.shape.size) / 2 : part.shape.radius)\n\n/**\n * The segment a hit lands on: `hit.part` when the caller resolved it (a segment id, or a region id for its first segment), else the attached\n * part whose surface is nearest to the local point.\n */\nexport const resolveSegment = (body: BodyState, spec: DestructibleSpec, part: string | undefined, localPoint: Vec3): SegmentId => {\n if (part !== undefined && isSegmentId(part)) return part\n if (part !== undefined && isBodyRegion(part)) return REGION_SEGMENTS[part][0] as SegmentId\n let best: SegmentId = 'torso'\n let bestGap = Infinity\n for (const candidate of spec.parts) {\n const segment = body.segments.find((entry) => entry.id === candidate.id)\n if (!segment?.attached) continue\n const gap = distance(candidate.position, localPoint) - radiusOf(candidate)\n if (gap < bestGap) [best, bestGap] = [segment.id, gap]\n }\n return best\n}\n\nexport const regionOfSegment = (body: BodyState, id: SegmentId): BodyRegion => body.segments.find((segment) => segment.id === id)?.region ?? 'torso'\n","import { segmentOf } from '../../body/body-state'\nimport type { SegmentState } from '../../types'\nimport type { BodyOps } from '../body-ops'\nimport { HEADSHOT, NO_HEADSHOT, bleedWound, destroyWithBleeding, segmentDamage, severWithBleeding } from './blow'\nimport type { SegmentBlow, SegmentRule } from './blow'\n\n/** A blow of at least this many points blows the head off (Arsenal `damage`: `dmg >= 30`). */\nconst HEAD_BLOW_POINTS = 30\nconst LIMB_VITALITY_SHARE = 0.3\n\nconst split = (ops: BodyOps): void => {\n const torso = segmentOf(ops.body, 'torso')\n if (!torso.attached) return\n severWithBleeding(ops, torso)\n ops.change('split', 'torso')\n ops.kill('vitality')\n}\n\nconst loseLimb = (ops: BodyOps, segment: SegmentState, blow: SegmentBlow): void => {\n if (blow.big || -segment.hp > segment.max) destroyWithBleeding(ops, segment)\n else severWithBleeding(ops, segment)\n const { body } = ops\n if (segment.kind === 'thigh' || segment.kind === 'shin') {\n if (body.alive) ops.crawl()\n } else if (segment.kind === 'foot' && body.alive && !body.crawl && body.limping.length === 0 && segment.side) ops.limp(segment.side)\n}\n\n/** The Galeria 3D do Arsenal's `damage`: every number and branch of the page, in its order. */\nexport const arsenalRule: SegmentRule = (ops, blow) => {\n const { segment } = blow\n if (!segment.attached) return NO_HEADSHOT\n const amount = segmentDamage(ops, blow, blow.points)\n if (blow.point) bleedWound(ops, segment, blow.point)\n segment.hp -= amount\n ops.damage(segment, amount, blow.damageType)\n let result = NO_HEADSHOT\n if (segment.kind === 'head') {\n if (blow.points >= HEAD_BLOW_POINTS || segment.hp <= 0) {\n destroyWithBleeding(ops, segment)\n ops.kill('head')\n result = HEADSHOT\n } else ops.wound(segment)\n } else if (segment.kind === 'jaw') {\n if (segment.hp <= 0) severWithBleeding(ops, segment)\n } else if (segment.kind === 'neck') {\n if (segment.hp <= 0) {\n severWithBleeding(ops, segment)\n ops.kill('head')\n }\n } else if (segment.kind === 'torso' || segment.kind === 'pelvis') {\n ops.body.vitality -= amount\n if (blow.points >= ops.rules.severity.splitAtDamage || segment.hp <= 0) split(ops)\n } else {\n ops.body.vitality -= amount * LIMB_VITALITY_SHARE\n if (segment.hp <= 0) loseLimb(ops, segment, blow)\n }\n if (ops.body.alive && ops.body.vitality <= 0) ops.kill('vitality')\n return result\n}\n","import type { SegmentKind } from '@adatechnology/game-contracts'\n\nimport { spreadPoints } from '../points'\nimport { HEADSHOT, NO_HEADSHOT, isLeg, segmentDamage } from './blow'\nimport type { SegmentRule } from './blow'\n\n/** A head at 0 is cut off by an edge of at least this `cut` or a blow of at least this many points (Elenco `hit`). */\nconst HEAD_SEVER_CUT = 0.7\nconst HEAD_SEVER_POINTS = 90\n/** The segments that hang from a joint of their own in the Elenco (`s.node`): they are cut or break at it. */\nconst JOINTED: ReadonlySet<SegmentKind> = new Set(['head', 'upperArm', 'forearm', 'hand', 'thigh', 'shin', 'foot'])\n\n/** The Elenco's `hit`, `sever` and `breakBone`: one ±15 % draw per blow, cut at the joint above, broken bones dangle or make the leg limp. */\nexport const elencoRule: SegmentRule = (ops, blow) => {\n const { segment } = blow\n const { body, rules } = ops\n if (!segment.attached || (!body.alive && segment.kind !== 'head')) return NO_HEADSHOT\n const amount = segmentDamage(ops, blow, spreadPoints(blow.points, rules.spread, ops.random))\n segment.hp = Math.max(0, segment.hp - amount)\n ops.damage(segment, amount, blow.damageType)\n if (segment.hp > 0) {\n ops.wound(segment)\n return NO_HEADSHOT\n }\n if (segment.kind === 'head') {\n if (blow.cut >= HEAD_SEVER_CUT || blow.points >= HEAD_SEVER_POINTS) ops.sever(segment, 'zero')\n else ops.breakBone(segment)\n ops.kill('head')\n return HEADSHOT\n }\n if (JOINTED.has(segment.kind)) {\n if (blow.cut >= rules.severity.severAtCut || amount >= segment.max * rules.severity.severAtDamageFraction) {\n ops.sever(segment, 'zero')\n if (isLeg(segment.kind)) ops.crawl()\n return NO_HEADSHOT\n }\n ops.breakBone(segment)\n if (isLeg(segment.kind) && segment.side) {\n ops.limp(segment.side)\n if (body.limping.length === 2) ops.crawl()\n }\n return NO_HEADSHOT\n }\n ops.breakBone(segment)\n if (segment.kind === 'torso') ops.kill('vitality')\n else if (segment.kind === 'pelvis') ops.crawl()\n else if (segment.kind === 'neck') ops.kill('head')\n return NO_HEADSHOT\n}\n","import { segmentOf } from '../../body/body-state'\nimport type { SegmentState } from '../../types'\nimport type { BodyOps } from '../body-ops'\nimport { spreadPoints } from '../points'\nimport { HEADSHOT, NO_HEADSHOT, bleedWound, destroyWithBleeding, isLeg, segmentDamage, severWithBleeding } from './blow'\nimport type { RuleResult, SegmentBlow, SegmentRule } from './blow'\n\ntype Outcome = 'destroyed' | 'severed' | 'broken'\n\n/** At 0: destroyed by a blast or a blow of twice the segment; severed by an edge (`cut` ≥ 0.5) or a blow above 90 % of it; else broken. */\nexport const severityOf = (ops: BodyOps, blow: SegmentBlow, amount: number, max: number): Outcome => {\n const rule = ops.rules.severity\n if (blow.explosive || amount >= max * rule.destroyAtDamageMultiple) return 'destroyed'\n if (blow.cut >= rule.severAtCut || amount > max * rule.severAtDamageFraction) return 'severed'\n return 'broken'\n}\n\nconst lose = (ops: BodyOps, segment: SegmentState, outcome: Outcome): void => {\n if (outcome === 'destroyed') destroyWithBleeding(ops, segment)\n else if (outcome === 'severed') severWithBleeding(ops, segment)\n else ops.breakBone(segment)\n}\n\n/** The game's head rule: a projectile kills when it pierces the skull with enough points, a blow when it takes the head's hit points. */\nconst hitHead = (ops: BodyOps, blow: SegmentBlow, points: number, amount: number, hpBefore: number): RuleResult => {\n const { segment, projectile } = blow\n const rule = ops.rules.severity\n const lethal = projectile ? blow.model.piercesSkull(projectile, blow.headResistance) && points >= rule.headKillDamage : amount >= hpBefore\n if (lethal) {\n const shotgunClose = projectile !== undefined && projectile.pellets > 1 && projectile.distance < rule.headBitShotgunMetres\n if (blow.explosive || points > rule.headBitDamage || shotgunClose) destroyWithBleeding(ops, segment)\n else ops.breakBone(segment)\n ops.kill('head')\n return HEADSHOT\n }\n ops.body.vitality -= amount\n ops.wound(segment)\n if (points > rule.jawDamage && ops.random() < rule.jawChance) severWithBleeding(ops, segmentOf(ops.body, 'jaw'))\n return NO_HEADSHOT\n}\n\nconst hitTorso = (ops: BodyOps, points: number, amount: number, segment: SegmentState): void => {\n ops.body.vitality -= amount\n if (points < ops.rules.severity.splitAtDamage && segment.hp > 0) return ops.wound(segment)\n const torso = segmentOf(ops.body, 'torso')\n if (!torso.attached) return\n severWithBleeding(ops, torso)\n ops.change('split', 'torso')\n if (ops.rules.deathRule === 'head-only') ops.crawl()\n else ops.kill('vitality')\n}\n\nconst hitLimb = (ops: BodyOps, blow: SegmentBlow, amount: number, hpBefore: number): void => {\n const { segment } = blow\n const rule = ops.rules.severity\n ops.body.vitality -= amount * rule.limbVitalityShare\n if (isLeg(segment.kind) && segment.side && segment.hp <= segment.max * rule.limpAtHpFraction) ops.limp(segment.side)\n if (segment.hp > 0 || hpBefore <= 0) return ops.wound(segment)\n const outcome = severityOf(ops, blow, amount, segment.max)\n lose(ops, segment, outcome)\n if (segment.kind === 'thigh' || segment.kind === 'shin') ops.crawl()\n}\n\n/** The kit's rule: Arsenal numbers, the design's severity, the game's head rule, the death rule of the kit. */\nexport const kitRule: SegmentRule = (ops, blow) => {\n const { segment } = blow\n if (!segment.attached) return NO_HEADSHOT\n const points = spreadPoints(blow.points, ops.rules.spread, ops.random)\n const amount = segmentDamage(ops, blow, points)\n if (blow.point && !blow.explosive) bleedWound(ops, segment, blow.point)\n const hpBefore = segment.hp\n segment.hp -= amount\n ops.damage(segment, amount, blow.damageType)\n let result = NO_HEADSHOT\n if (segment.kind === 'head') result = hitHead(ops, blow, points, amount, hpBefore)\n else if (segment.kind === 'torso' || segment.kind === 'pelvis') hitTorso(ops, points, amount, segment)\n else if (segment.kind === 'jaw' || segment.kind === 'neck') {\n if (segment.hp <= 0 && hpBefore > 0) {\n lose(ops, segment, severityOf(ops, blow, amount, segment.max))\n if (segment.kind === 'neck' && !segment.attached) ops.kill('head')\n } else ops.wound(segment)\n } else hitLimb(ops, blow, amount, hpBefore)\n if (ops.body.vitality <= 0) ops.kill('vitality')\n if (ops.body.alive && points >= ops.rules.severity.stunAtPoints) ops.stun()\n return result\n}\n","import type { DestructibleSpec, Vec3 } from '@adatechnology/game-contracts'\n\nimport { segmentOf } from '../body/body-state'\nimport { REGION_SEGMENTS } from '../body/regions'\nimport { segmentNode } from '../body/segment-tree'\nimport type { SegmentId } from '../body/segment-tree'\nimport { regionBlast, segmentBlast } from './blast'\nimport type { BodyOps } from './body-ops'\nimport type { DamageSetup } from './damage-character'\nimport { energyKept, segmentResistance } from './penetration'\nimport { cutOf, pointsFromEnergy, projectileOf, resolvePoints } from './points'\nimport { layersOn, protect } from './protection'\nimport type { ProtectionOutcome } from './protection'\nimport { resolveSegment, regionOfSegment } from './resolve-part'\nimport { arsenalRule } from './rules/arsenal'\nimport type { RuleResult, SegmentRule } from './rules/blow'\nimport { elencoRule } from './rules/elenco'\nimport { kitRule } from './rules/kit'\nimport { regionRule } from './rules/regions'\nimport type { BodyHit, HitReport, ProtectionLayer } from './types'\n\nconst SEGMENT_RULES: Readonly<Record<string, SegmentRule>> = { kit: kitRule, arsenal: arsenalRule, elenco: elencoRule }\nconst HEAD_RESISTANCE = segmentResistance({ kind: 'head', bodyCount: 1, protection: 0 })\nconst NO_PROTECTION: ProtectionOutcome = { ballistic: 1, resistance: 0, limbs: 1, fire: 1 }\nconst ABSORBED_SPARKS = 8\nconst METRES_PER_MM = 0.001\n\nexport type ApplyBlowParams = {\n readonly ops: BodyOps\n readonly hit: BodyHit\n readonly setup: DamageSetup\n readonly worn: readonly ProtectionLayer[]\n readonly localPoint: Vec3\n readonly jointOf: (id: SegmentId) => Vec3\n readonly describe: () => DestructibleSpec\n}\n\nconst report = (ops: BodyOps, fields: Partial<HitReport> & { points: number }, result: RuleResult = { headshot: false }): HitReport => ({\n through: false,\n exitEnergy: 0,\n ...fields,\n killed: !ops.body.alive,\n headshot: result.headshot,\n})\n\n/** Fire and heat: the exposure burns the torso (`burnPointsPerSecond` × seconds), less what the clothing keeps off. */\nconst burn = ({ ops, hit, setup, worn }: ApplyBlowParams): HitReport => {\n const torso = segmentOf(ops.body, 'torso')\n const fire = protect({ layers: layersOn(worn, segmentNode('torso').slots, ops.body.consumed), model: setup.model }).fire\n const points = setup.rules.burnPointsPerSecond * (hit.duration ?? 0) * fire\n ops.body.vitality -= points\n ops.damage(torso, points, hit.type)\n if (ops.body.vitality <= 0) ops.kill('vitality')\n return report(ops, { part: 'torso', points })\n}\n\nconst blast = ({ ops, hit, setup, localPoint, jointOf }: ApplyBlowParams): HitReport => {\n const points = hit.points ?? pointsFromEnergy(hit.energy ?? 0, setup.rules)\n const base = { ops, center: localPoint, points, radius: hit.radius ?? 1, ...(hit.lethalRadius !== undefined ? { lethalRadius: hit.lethalRadius } : {}), jointOf }\n const common = { cut: hit.cut ?? setup.rules.defaultCut.explosive, damageType: hit.type, model: setup.model, headResistance: HEAD_RESISTANCE }\n const rule = SEGMENT_RULES[setup.rules.segmentRule] ?? kitRule\n const result =\n ops.body.detail === 'regions'\n ? regionBlast({ ...base, blow: { ...common, protection: NO_PROTECTION } })\n : segmentBlast({ ...base, rule, blow: { ...common, limbFactor: ops.spec.limbFactor } })\n return report(ops, { points }, result)\n}\n\nconst DEFAULT_PATH_METRES = 0.2\n\n/** Length of the path through a part (its diameter), for the exit point of a projectile that goes through. */\nconst pathThrough = (spec: DestructibleSpec, id: SegmentId): number => {\n const shape = spec.parts.find((part) => part.id === id)?.shape\n return shape && shape.kind !== 'box' ? 2 * shape.radius : DEFAULT_PATH_METRES\n}\n\nconst exitOf = (hit: BodyHit, depth: number): Vec3 => {\n const [x, y, z] = hit.direction ?? [0, 0, -1]\n return [hit.point[0] + x * depth, hit.point[1] + y * depth, hit.point[2] + z * depth]\n}\n\n/** Bullets, blades and blunt blows: resolve the segment, the protection, the penetration, the points; then the detail's rule decides. */\nconst direct = ({ ops, hit, setup, worn, localPoint, describe }: ApplyBlowParams): HitReport => {\n const { body, spec, rules } = ops\n const caliber = hit.caliberId === undefined ? undefined : setup.calibers.get(hit.caliberId)\n const projectile = hit.type === 'ballistic' ? projectileOf(hit, caliber) : undefined\n const id = resolveSegment(body, describe(), hit.part, localPoint)\n const region = regionOfSegment(body, id)\n const slots = segmentNode(body.detail === 'regions' ? (REGION_SEGMENTS[region][0] as SegmentId) : id).slots\n const protection = protect({ layers: layersOn(worn, slots, body.consumed), model: setup.model, ...(projectile ? { projectile } : {}) })\n if (protection.absorbedBy) {\n body.consumed.add(protection.absorbedBy)\n ops.emit({ type: 'debris', part: id, kind: 'sparks', point: hit.point, normal: [0, 1, 0], count: ABSORBED_SPARKS, speed: 3 })\n return report(ops, { part: id, points: 0, absorbedBy: protection.absorbedBy })\n }\n const rawPoints = resolvePoints(hit, caliber, rules)\n const points = rawPoints * protection.ballistic\n const cut = cutOf(hit, projectile, rules)\n const segment = segmentOf(body, id)\n const resistance = segmentResistance({ kind: segment.kind, bodyCount: spec.bodyCount, protection: protection.resistance })\n const through = setup.model.id === 'physical' && projectile !== undefined && projectile.force > resistance\n const exitEnergy = through && projectile ? (hit.energy ?? 0) * energyKept(projectile.force, resistance) : 0\n if (projectile) {\n const depth = pathThrough(describe(), id)\n ops.emit({ type: 'hole', part: id, hole: { point: localPoint, normal: [0, 0, 1], diameter: (hit.caliber ?? 9) * METRES_PER_MM, through }, worldPoint: hit.point, ...(through ? { exitPoint: exitOf(hit, depth) } : {}) })\n }\n const common = { points, cut, damageType: hit.type, model: setup.model, headResistance: HEAD_RESISTANCE, ...(projectile ? { projectile } : {}) }\n const result =\n body.detail === 'regions'\n ? regionRule(ops, { ...common, points: rawPoints, region, protection })\n : (SEGMENT_RULES[rules.segmentRule] ?? kitRule)(ops, {\n ...common,\n segment,\n explosive: false,\n big: points > rules.blast.bigPoints,\n limbFactor: spec.limbFactor * protection.limbs,\n ...(hit.woundAtPoint === false ? {} : { point: hit.point }),\n })\n return report(ops, { part: id, points, through, exitEnergy }, result)\n}\n\nexport const applyBlow = (params: ApplyBlowParams): HitReport => {\n if (params.hit.type === 'fire' || params.hit.type === 'heat') return burn(params)\n if (params.hit.type === 'explosive') return blast(params)\n return direct(params)\n}\n","import type { DestructibleImpl, DestructionEvent, Hit, Vec3 } from '@adatechnology/game-contracts'\n\nimport type { BodyState } from '../body/body-state'\nimport { segmentNode } from '../body/segment-tree'\nimport type { SegmentId, SegmentSide } from '../body/segment-tree'\nimport { toLocal, toWorld } from '../body/transform'\nimport { characterView } from '../character'\nimport type { Character, CharacterCore } from '../character'\nimport { stepBleeding } from './bleeding'\nimport type { Bleeder } from './bleeding'\nimport { createBodyOps } from './body-ops'\nimport type { BodyOps } from './body-ops'\nimport { segmentResistance } from './penetration'\nimport { applyBlow } from './pipeline'\nimport { createRng } from './points'\nimport { layeredProtection, layersOn } from './protection'\nimport { resolveSegment } from './resolve-part'\nimport type { BodyHit, CaliberEntry, DamageRules, HitReport, PenetrationModel, ProtectionLayer } from './types'\n\n/** A character with the damage model: a `DestructibleImpl` a destruction world can host next to its own objects. */\nexport type DamageCharacter = Character &\n DestructibleImpl & {\n readonly alive: boolean\n /** The sides that limp, in the order they started. */\n readonly limping: readonly SegmentSide[]\n /** Seconds of stagger left from a heavy hit. */\n readonly stunSeconds: number\n /** What the last `hit` did (points, kill, headshot, through). */\n readonly lastHit?: HitReport\n /** The bleeding wounds, oldest first. */\n bleeders(): readonly Readonly<Bleeder>[]\n /** 0..1 protection of the layers over a segment against a bite or a scratch (the layered T3 formula, capped at 90 %). */\n protectionAgainst(attack: 'bite' | 'scratch', part: SegmentId): number\n /** Ids of the protection layers worn and not used up (a helmet that took its shot is gone). */\n intactProtection(): readonly string[]\n /** Penetration resistance R of the path through a part (a segment or a region id), with the protection worn over it. */\n resistanceOf(part: string): number\n hit(hit: Hit | BodyHit): DestructionEvent[]\n /** Ages bleeders (a `leak` per second each) and the stun. */\n update(dt: number): DestructionEvent[]\n serialize(): unknown\n load(data: unknown): void\n }\n\nexport type DamageSetup = {\n readonly rules: DamageRules\n readonly model: PenetrationModel\n readonly protection: ReadonlyMap<string, ProtectionLayer>\n readonly calibers: ReadonlyMap<string, CaliberEntry>\n}\n\ntype Saved = { body: Omit<BodyState, 'consumed'> & { consumed: string[] }; bleeders: Bleeder[]; hitCounter: number; clock: number }\n\nexport const createDamageCharacter = (core: CharacterCore, setup: DamageSetup): DamageCharacter => {\n const view = characterView(core)\n const worn = core.spec.protection.map((id) => setup.protection.get(id)).filter((layer): layer is ProtectionLayer => layer !== undefined)\n let bleeders: Bleeder[] = []\n let hitCounter = 0\n let clock = 0\n let lastHit: HitReport | undefined\n const transform = () => ({ position: core.position, rotation: core.rotation })\n const jointOf = (id: SegmentId): Vec3 => core.rig.joints[segmentNode(id).joint]\n const pointOf = (id: SegmentId): Vec3 => toWorld(transform(), jointOf(id))\n const opsFor = (random: () => number, source?: string): BodyOps =>\n createBodyOps({ body: core.body, spec: core.spec, rules: setup.rules, random, time: clock, pointOf, bleeders, ...(source !== undefined ? { source } : {}) })\n\n const character: DamageCharacter = {\n ...view,\n get segments() {\n return core.body.segments\n },\n get detail() {\n return core.body.detail\n },\n get alive() {\n return core.body.alive\n },\n get limping() {\n return [...core.body.limping]\n },\n get stunSeconds() {\n return core.body.stunSeconds\n },\n get lastHit() {\n return lastHit\n },\n name: core.spec.kind,\n hit(raw) {\n const hit = raw as BodyHit\n hitCounter += 1\n const random = core.spec.random ?? createRng((core.spec.seed ^ hitCounter) >>> 0)\n const ops = opsFor(random, hit.source)\n lastHit = applyBlow({ ops, hit, setup, worn, localPoint: toLocal(transform(), hit.point), jointOf, describe: core.describe })\n return ops.events\n },\n update(dt) {\n clock += dt\n core.body.stunSeconds = Math.max(0, core.body.stunSeconds - dt)\n const ops = opsFor(() => 0)\n stepBleeding({ bleeders, dt, emit: ops.emit, pointOf })\n return ops.events\n },\n bleeders: () => bleeders.map((bleeder) => ({ ...bleeder })),\n intactProtection: () => core.spec.protection.filter((id) => !core.body.consumed.has(id)),\n resistanceOf(part) {\n const id = resolveSegment(core.body, core.describe(), part, [0, 0, 0])\n const layers = layersOn(worn, segmentNode(id).slots, core.body.consumed)\n const protection = layers.reduce((sum, layer) => sum + (layer.ballistic?.resistance ?? 0), 0)\n return segmentResistance({ kind: segmentNode(id).kind, bodyCount: core.spec.bodyCount, protection })\n },\n protectionAgainst: (attack, part) => layeredProtection({ layers: layersOn(worn, segmentNode(part).slots, core.body.consumed), attack }),\n reset() {\n core.resetBody()\n bleeders = []\n hitCounter = 0\n lastHit = undefined\n },\n serialize(): Saved {\n const { consumed, ...rest } = core.body\n return { body: { ...structuredClone(rest), consumed: [...consumed] }, bleeders: structuredClone(bleeders), hitCounter, clock }\n },\n load(data) {\n const saved = data as Saved\n Object.assign(core.body, structuredClone(saved.body), { consumed: new Set(saved.body.consumed) })\n bleeders = structuredClone(saved.bleeders)\n hitCounter = saved.hitCounter\n clock = saved.clock\n },\n }\n return character\n}\n","import type { DestructionEvent, Vec3 } from '@adatechnology/game-contracts'\n\nimport { isBodyRegion } from '../body/regions'\nimport { isSegmentId, segmentNode } from '../body/segment-tree'\nimport type { DamageCharacter } from './damage-character'\nimport { TEAM_GAME_RULES } from './defaults'\nimport { energyKept, teamGameCost, teamGameFalloff } from './penetration'\nimport { penetrationForce } from './points'\nimport type { CaliberEntry } from './types'\n\n/** One body in the line of fire, `distance` metres from the muzzle. */\nexport type LineTarget = { readonly character: DamageCharacter; readonly part: string; readonly distance: number; readonly point?: Vec3 }\n\n/** What the line needs from a shot (a `Shot` of game-weapons fits). */\nexport type LineShot = {\n readonly energyAt: (distance: number) => number\n /** Projectile grams. */\n readonly mass: number\n /** Diameter in mm. */\n readonly caliber: number\n readonly caliberId?: string\n readonly source?: string\n}\n\nexport type LineHit = { readonly index: number; readonly points: number; readonly energy: number; readonly killed: boolean; readonly headshot: boolean; readonly events: DestructionEvent[] }\nexport type LineResult = { readonly hits: LineHit[]; /** 1-based index of the last body hit (0: none). */ readonly stoppedAt: number }\n\nexport type PenetrateLineParams = {\n readonly model: 'physical' | 'team-game'\n readonly shot: LineShot\n readonly targets: readonly LineTarget[]\n readonly calibers: ReadonlyMap<string, CaliberEntry>\n}\n\n/** After a kill the game restarts the ray 0.3 m past the body and measures the next distances from there (`shootRay`). */\nconst RESTART_METRES = 0.3\n\nconst regionOfPart = (part: string) => (isSegmentId(part) ? segmentNode(part).region : isBodyRegion(part) ? part : 'torso')\n\nconst lineHit = (index: number, target: LineTarget, fields: { points: number; energy: number; events: DestructionEvent[] }): LineHit => ({\n index,\n ...fields,\n killed: !target.character.alive,\n headshot: target.character.lastHit?.headshot ?? false,\n})\n\n/** The game's `shootRay`: penetration points spent per body (head 0.7, torso 1, a brute 2, limb 0.5), 75 % of the damage carried on. */\nconst teamGameLine = ({ shot, targets, calibers }: PenetrateLineParams): LineResult => {\n const caliber = shot.caliberId === undefined ? undefined : calibers.get(shot.caliberId)\n if (caliber?.penetration === undefined || caliber.points === undefined) throw new Error(`game-characters: the team-game line needs a calibre with points and penetration (\"${shot.caliberId}\")`)\n let penetration = caliber.penetration\n let points = caliber.points\n let origin = 0\n const hits: LineHit[] = []\n for (const [index, target] of targets.entries()) {\n if (!target.character.alive || target.distance - origin <= 0) continue\n const distance = target.distance - origin\n const dealt = points * teamGameFalloff(distance, caliber.effectiveRangeMetres ?? Infinity)\n const events = target.character.hit({ type: 'ballistic', point: target.point ?? [0, 0, 0], part: target.part, points: dealt, caliberId: caliber.id, distance, ...(shot.source ? { source: shot.source } : {}) })\n hits.push(lineHit(index, target, { points: dealt, energy: shot.energyAt(target.distance), events }))\n penetration -= teamGameCost(regionOfPart(target.part), target.character.spec.bodyCount)\n points *= TEAM_GAME_RULES.damageKeptPerBody\n if (penetration <= 0) break\n if (!target.character.alive) origin = target.distance + RESTART_METRES\n }\n return { hits, stoppedAt: hits.length === 0 ? 0 : (hits[hits.length - 1]?.index ?? -1) + 1 }\n}\n\n/** P7: the force P = √(E·m/A) hits a body while it is above 0, loses the body's resistance R and keeps P/(P+R) of the energy. */\nconst physicalLine = ({ shot, targets }: PenetrateLineParams): LineResult => {\n const first = targets[0]\n let force = first ? penetrationForce(shot.energyAt(first.distance), shot.mass, shot.caliber) : 0\n let kept = 1\n const hits: LineHit[] = []\n for (const [index, target] of targets.entries()) {\n if (force <= 0) break\n if (!target.character.alive) continue\n const energy = shot.energyAt(target.distance) * kept\n const events = target.character.hit({ type: 'ballistic', point: target.point ?? [0, 0, 0], part: target.part, energy, mass: shot.mass, caliber: shot.caliber, distance: target.distance, ...(shot.caliberId ? { caliberId: shot.caliberId } : {}) })\n hits.push(lineHit(index, target, { points: target.character.lastHit?.points ?? 0, energy, events }))\n const resistance = target.character.resistanceOf(target.part)\n kept *= energyKept(force, resistance)\n force -= resistance\n }\n return { hits, stoppedAt: hits.length === 0 ? 0 : (hits[hits.length - 1]?.index ?? -1) + 1 }\n}\n\n/** A shot through a line of bodies, nearest first. Each body takes the hit through its own damage model. */\nexport const penetrateLine = (params: PenetrateLineParams): LineResult => (params.model === 'team-game' ? teamGameLine(params) : physicalLine(params))\n","type Entry = { readonly id: string }\n\n/** The shipped entries with the ones from `extra` added or, when the id exists, replaced. */\nexport const mergeById = <TEntry extends Entry>(shipped: readonly TEntry[], extra: readonly TEntry[] | undefined): Map<string, TEntry> => {\n const entries = new Map<string, TEntry>()\n for (const entry of [...shipped, ...(extra ?? [])]) entries.set(entry.id, entry)\n return entries\n}\n\n/** Applies `patch` by id (a shallow merge); a patch for an id that does not exist is ignored. */\nexport const applyPatches = <TEntry extends Entry>(entries: Map<string, TEntry>, patches: Readonly<Record<string, Partial<TEntry>>> | undefined): void => {\n for (const [id, patch] of Object.entries(patches ?? {})) {\n const entry = entries.get(id)\n if (entry) entries.set(id, { ...entry, ...patch, id })\n }\n}\n\nexport const removeIds = (entries: Map<string, unknown>, ids: readonly string[] | undefined): void => {\n for (const id of ids ?? []) entries.delete(id)\n}\n","import { createBodySpec } from './body/body-spec'\nimport { createCorpseLedger } from './corpses'\nimport type { CorpseLedger } from './corpses'\nimport type { BodySpec } from './body/body-spec'\nimport { createCharacterCore, resolveSpec } from './character'\nimport { createDamageCharacter } from './damage/damage-character'\nimport type { DamageCharacter } from './damage/damage-character'\nimport { DAMAGE_PRESETS, PROTECTION_PRESETS, TEAM_GAME_CALIBERS } from './damage/defaults'\nimport { penetrateLine } from './damage/line'\nimport type { LineResult, LineShot, LineTarget } from './damage/line'\nimport { PENETRATION_MODELS } from './damage/penetration'\nimport type { CaliberEntry, DamageRules, PenetrationModel, ProtectionLayer } from './damage/types'\nimport { applyPatches, mergeById, removeIds } from './registry'\nimport type { CharacterPreset, CharacterSpec, CharactersOptions, CorpseOptions, DamageOptions } from './types'\n\nexport const DEFAULT_CORPSES: CorpseOptions = { max: 400, seconds: 900 }\n\n/** The base preset every spec can start from: an unnamed adult person. */\nexport const PERSON_PRESET: CharacterPreset = { id: 'person', kind: 'person', age: 'adult' }\n\nexport type CharacterKit = {\n readonly body: BodySpec\n readonly presets: ReadonlyMap<string, CharacterPreset>\n readonly corpses: CorpseOptions\n readonly damage: DamageRules\n readonly penetration: PenetrationModel\n readonly protection: ReadonlyMap<string, ProtectionLayer>\n readonly calibers: ReadonlyMap<string, CaliberEntry>\n /** A new character: the preset (`spec.preset`, else the one named `spec.kind`) under the spec. */\n create(spec: CharacterSpec): DamageCharacter\n /** The bodies left on the ground, capped and timed by the kit's `corpses` option. */\n createCorpses<TData>(): CorpseLedger<TData>\n /** A shot through a line of bodies with the kit's penetration model and calibre table. */\n penetrateLine(shot: LineShot, targets: readonly LineTarget[]): LineResult\n}\n\n/** Fills a spec from its preset: what the spec says wins; `multipliers` merge field by field. */\nexport const applyPreset = (spec: CharacterSpec, presets: ReadonlyMap<string, CharacterPreset>): CharacterSpec => {\n const preset = presets.get(spec.preset ?? spec.kind)\n if (!preset) return spec\n const { id: _presetId, ...defaults } = preset\n const multipliers = { ...defaults.multipliers, ...spec.multipliers }\n return { ...defaults, ...spec, multipliers }\n}\n\n/** The rules of a preset (`kit` by default) with the given fields replaced; `severity`, `blast` and `segments` merge key by key. */\nexport const resolveDamageRules = (options: DamageOptions = {}): DamageRules => {\n const { preset, severity, blast, segments, ...rest } = options\n const base = DAMAGE_PRESETS[preset ?? 'kit']\n return { ...base, ...rest, severity: { ...base.severity, ...severity }, blast: { ...base.blast, ...blast }, segments: { ...base.segments, ...segments } }\n}\n\nconst modelOf = (option: CharactersOptions['penetration']): PenetrationModel => (typeof option === 'object' ? option : PENETRATION_MODELS[option ?? 'physical'])\n\nexport const createCharacters = (options: CharactersOptions = {}): CharacterKit => {\n const body = createBodySpec(options.body)\n const packs = options.packs ?? []\n const presets = mergeById([PERSON_PRESET], packs.flatMap((pack) => pack.presets ?? []))\n applyPatches(presets, options.patch)\n removeIds(presets, options.remove)\n const damage = resolveDamageRules(options.damage)\n const penetration = modelOf(options.penetration)\n const protection = mergeById(PROTECTION_PRESETS, [...packs.flatMap((pack) => pack.protection ?? []), ...(options.protection ?? [])])\n const shippedCalibers = penetration.id === 'team-game' ? TEAM_GAME_CALIBERS : []\n const calibers = mergeById(shippedCalibers, [...packs.flatMap((pack) => pack.calibers ?? []), ...(options.calibers ?? [])])\n const setup = { rules: damage, model: penetration, protection, calibers }\n let counter = 0\n return {\n body,\n presets,\n corpses: { ...DEFAULT_CORPSES, ...options.corpses },\n damage,\n penetration,\n protection,\n calibers,\n create(spec) {\n counter += 1\n const resolved = resolveSpec(applyPreset(spec, presets), body, counter)\n const core = createCharacterCore({ spec: resolved, bodySpec: body, hitPointsOf: (kind) => damage.segments[kind].hitPoints })\n return createDamageCharacter(core, setup)\n },\n createCorpses: () => createCorpseLedger({ ...DEFAULT_CORPSES, ...options.corpses }),\n penetrateLine: (shot, targets) => penetrateLine({ model: penetration.id === 'team-game' ? 'team-game' : 'physical', shot, targets, calibers }),\n }\n}\n","{\n \"cascade\": {\n \"hip\": 16,\n \"spine\": 11,\n \"shoulder\": 9,\n \"elbow\": 7,\n \"leg\": 14,\n \"knee\": 11,\n \"head\": 6\n },\n \"moves\": {\n \"idle\": {\n \"gait\": 0,\n \"freq\": 0,\n \"amp\": 0,\n \"knee\": 0,\n \"bob\": 0,\n \"lean\": 0,\n \"arm\": 0,\n \"elb\": 0.12,\n \"crouch\": 0,\n \"aim\": 0,\n \"turn\": 0,\n \"grip\": 0.35\n },\n \"walk\": {\n \"gait\": 1,\n \"freq\": 5.6,\n \"amp\": 0.42,\n \"knee\": 0.85,\n \"bob\": 0.035,\n \"lean\": 0.05,\n \"arm\": 0.42,\n \"elb\": 0.3,\n \"crouch\": 0,\n \"aim\": 0,\n \"turn\": 0,\n \"grip\": 0.4\n },\n \"run\": {\n \"gait\": 1,\n \"freq\": 9.2,\n \"amp\": 0.72,\n \"knee\": 1.5,\n \"bob\": 0.06,\n \"lean\": 0.3,\n \"arm\": 0.85,\n \"elb\": 1.35,\n \"crouch\": 0,\n \"aim\": 0,\n \"turn\": 0,\n \"grip\": 1.1\n },\n \"crouch\": {\n \"gait\": 1,\n \"freq\": 3.8,\n \"amp\": 0.3,\n \"knee\": 0.6,\n \"bob\": 0.02,\n \"lean\": 0.42,\n \"arm\": 0.15,\n \"elb\": 0.7,\n \"crouch\": 1,\n \"aim\": 0,\n \"turn\": 0,\n \"grip\": 0.8\n },\n \"aim\": {\n \"gait\": 0,\n \"freq\": 0,\n \"amp\": 0,\n \"knee\": 0,\n \"bob\": 0,\n \"lean\": 0.06,\n \"arm\": 0,\n \"elb\": 0.2,\n \"crouch\": 0.25,\n \"aim\": 1,\n \"turn\": 0,\n \"grip\": 1.2\n },\n \"turn\": {\n \"gait\": 0.5,\n \"freq\": 4.2,\n \"amp\": 0.14,\n \"knee\": 0.7,\n \"bob\": 0.012,\n \"lean\": 0.03,\n \"arm\": 0.12,\n \"elb\": 0.25,\n \"crouch\": 0,\n \"aim\": 0,\n \"turn\": 1,\n \"grip\": 0.4\n }\n },\n \"poses\": [\n {\n \"index\": 0,\n \"id\": \"walk\",\n \"name\": {\n \"pt-BR\": \"anda\"\n }\n },\n {\n \"index\": 1,\n \"id\": \"crawl\",\n \"name\": {\n \"pt-BR\": \"rasteja\"\n }\n },\n {\n \"index\": 2,\n \"id\": \"fallen\",\n \"name\": {\n \"pt-BR\": \"caído\"\n }\n },\n {\n \"index\": 3,\n \"id\": \"attack\",\n \"name\": {\n \"pt-BR\": \"ataca\"\n }\n },\n {\n \"index\": 4,\n \"id\": \"scream\",\n \"name\": {\n \"pt-BR\": \"grito\"\n }\n },\n {\n \"index\": 5,\n \"id\": \"crouch\",\n \"name\": {\n \"pt-BR\": \"agachado\"\n }\n },\n {\n \"index\": 6,\n \"id\": \"leap\",\n \"name\": {\n \"pt-BR\": \"salto\"\n }\n },\n {\n \"index\": 7,\n \"id\": \"eat\",\n \"name\": {\n \"pt-BR\": \"comendo\"\n }\n }\n ],\n \"walk\": {\n \"cadenceBase\": 0.5,\n \"cadencePerSpeed\": 0.3,\n \"stopBelowSpeed\": 0.05,\n \"maxSine\": 0.9,\n \"strideFactor\": 4,\n \"legLengthFactor\": 0.9\n }\n}\n","import gait from '../data/gait.json'\n\nconst WALK = gait.walk\n\n/** Cycles per second at `speed` m/s (the game's `walkCad`). */\nexport const walkCadence = (speed: number): number => WALK.cadenceBase + WALK.cadencePerSpeed * speed\n\n/** Hip swing in radians at `speed` m/s for a body `height` times the base height: the stride that makes the foot meet the ground (the game's `walkGait`). */\nexport const walkGait = (speed: number, height = 1): number =>\n speed < WALK.stopBelowSpeed ? 0 : 2 * Math.asin(Math.min(WALK.maxSine, speed / (WALK.strideFactor * WALK.legLengthFactor * height * walkCadence(speed))))\n\nexport type StrideParams = {\n readonly speed: number\n readonly height?: number\n /** Default true: cadence and swing come from the speed, so the feet do not slide. False keeps the profile's own numbers (the Bestiário preset). */\n readonly strideFromSpeed?: boolean\n}\n\nexport type Stride = {\n /** Cycles per second. */\n readonly frequency: number\n /** Thigh swing, radians. */\n readonly swing: number\n /** Knee bend, radians. */\n readonly kneeBend: number\n}\n\nconst SWING_SHARE = 0.5\nconst KNEE_PER_GAIT = 0.85\n\n/** The gait numbers for a speed: from the ground-matching stride, or `fallback` (the profile) when `strideFromSpeed` is false. */\nexport const strideFor = ({ speed, height = 1, strideFromSpeed = true }: StrideParams, fallback: Stride): Stride => {\n if (!strideFromSpeed) return fallback\n const amplitude = walkGait(speed, height)\n return { frequency: walkCadence(speed), swing: amplitude * SWING_SHARE, kneeBend: amplitude * KNEE_PER_GAIT }\n}\n","import gait from '../data/gait.json'\n\n/** How a body type walks: offsets over its rest pose (the Bestiário's `GAIT`). `f` cycles per second, `a` thigh swing, `k` knee bend, `arm` arm swing. */\nexport type GaitProfile = {\n readonly f: number\n readonly a?: number\n readonly k?: number\n readonly arm?: number\n readonly bob?: number\n readonly sway?: number\n readonly drag?: boolean\n readonly crawl?: boolean\n readonly idle?: boolean\n readonly eat?: boolean\n readonly leap?: boolean\n readonly listen?: boolean\n readonly stalk?: boolean\n readonly sniff?: boolean\n}\n\nexport type JointAngles = { readonly shoulder: number; readonly elbow: number }\nexport type LegAngles = { readonly hip: number; readonly knee: number; readonly lost?: boolean }\n\n/**\n * The pose the gait swings around. `arms[0]` is the right arm and `arms[1]` the left; `legs[0]` is the left leg and `legs[1]` the right\n * (the order the Bestiário builds them in). `hipY` is the rest height of the hips.\n */\nexport type RestPose = {\n readonly hipY: number\n readonly lean: number\n readonly headX: number\n readonly arms: readonly [JointAngles, JointAngles]\n readonly legs: readonly [LegAngles, LegAngles]\n}\n\n/** What a gait sets this frame; a field the gait does not write stays `undefined` and the joint keeps what it had. */\nexport type GaitSample = {\n hipY?: number\n upper: { x?: number; y?: number; z?: number }\n head: { x?: number; y?: number }\n arms: { shoulder?: number; elbow?: number }[]\n legs: { hip?: number; knee?: number }[]\n}\n\nexport const emptySample = (): GaitSample => ({ upper: {}, head: {}, arms: [{}, {}], legs: [{}, {}] })\n\nexport type CascadeJoint = keyof typeof gait.cascade\n\n/** Cascade rates per joint (1/s): each joint reaches its target with a delay, from the hips to the head (Bestiário 12.3). */\nexport const CASCADE: Readonly<Record<CascadeJoint, number>> = gait.cascade\n\n/** The 8 poses of the instanced body, in the order of the game's `iB.w`. */\nexport const INSTANCE_POSES = ['walk', 'crawl', 'fallen', 'attack', 'scream', 'crouch', 'leap', 'eat'] as const\nexport type InstancePose = (typeof INSTANCE_POSES)[number]\n\nconst MIN_HEIGHT = -2\nconst MAX_HEIGHT = 8\nconst HEIGHT_STEPS = 1000\nconst POSE_SLOTS = 16\n\n/** `iB.w` of the instanced body: the pose plus 16 times the ground height in millimetres (a pile of bodies, a jump). */\nexport const encodePoseHeight = (pose: InstancePose, height = 0): number =>\n INSTANCE_POSES.indexOf(pose) + POSE_SLOTS * Math.round((Math.min(MAX_HEIGHT, Math.max(MIN_HEIGHT, height)) - MIN_HEIGHT) * HEIGHT_STEPS)\n\nexport const decodePoseHeight = (encoded: number): { readonly pose: InstancePose; readonly height: number } => {\n const height = Math.floor(encoded / POSE_SLOTS) / HEIGHT_STEPS + MIN_HEIGHT\n return { pose: INSTANCE_POSES[encoded - Math.floor(encoded / POSE_SLOTS) * POSE_SLOTS] as InstancePose, height }\n}\n","import { emptySample } from './profile'\nimport type { GaitProfile, GaitSample, RestPose } from './profile'\nimport { strideFor } from './stride'\nimport type { StrideParams } from './stride'\n\nconst TWO_PI = Math.PI * 2\nconst LEAP_AIR_SHARE = 0.38\nconst LEAP_PHASE_DIVISOR = 6.3\nconst DEFAULT_PROFILE: GaitProfile = { f: 1.1, a: 0.28, k: 0.35, drag: true, arm: 0.08 }\n\nexport type AnimateProfileParams = {\n readonly profile?: GaitProfile\n readonly rest: RestPose\n /** Seconds. */\n readonly time: number\n /** Per-body phase offset, radians (the page's `rig.ph`). */\n readonly phase: number\n /** With `strideFromSpeed`, the speed and height that set cadence and swing. Without it the profile's own numbers are used. */\n readonly stride?: StrideParams\n}\n\n/** The leap, as a cycle: crouched, then airborne for 38% of it. */\nconst leap = ({ rest, time, phase, profile }: Required<Pick<AnimateProfileParams, 'rest' | 'time' | 'phase'>> & { profile: GaitProfile }): GaitSample => {\n const sample = emptySample()\n const cycle = (time * profile.f + phase / LEAP_PHASE_DIVISOR) % 1\n const air = cycle < LEAP_AIR_SHARE ? Math.sin((cycle / LEAP_AIR_SHARE) * Math.PI) : 0\n sample.hipY = rest.hipY + air * 0.95\n sample.upper.x = rest.lean - air * 0.45\n rest.legs.forEach((leg, index) => (sample.legs[index] = { hip: leg.hip * (1 - air * 0.7), knee: leg.knee * (1 - air * 0.75) }))\n rest.arms.forEach((arm, index) => (sample.arms[index] = { shoulder: arm.shoulder - air * 2.3, elbow: arm.elbow * (1 - air) }))\n return sample\n}\n\n/** Joint targets of one gait at `time` (the Bestiário's `animate0`), as numbers; the rig applies the ones that are set. */\nexport const animateProfile = ({ profile = DEFAULT_PROFILE, rest, time, phase, stride }: AnimateProfileParams): GaitSample => {\n const own = { frequency: profile.f, swing: profile.a ?? 0, kneeBend: profile.k ?? 0 }\n const { frequency, swing, kneeBend } = stride ? strideFor(stride, own) : own\n const angle = time * frequency * TWO_PI + phase\n const sine = Math.sin(angle)\n const cosine = Math.cos(angle)\n const sample = emptySample()\n if (profile.leap) return leap({ rest, time, phase, profile })\n if (profile.listen) {\n sample.head.y = Math.sin(time * 0.7 + phase) * 0.6\n rest.arms.forEach((arm, index) => (sample.arms[index] = { shoulder: arm.shoulder + Math.sin(time * 0.9 + index) * 0.08 }))\n return sample\n }\n if (profile.eat) {\n const wave = Math.sin(time * profile.f * TWO_PI + phase)\n sample.head.x = rest.headX + Math.max(0, wave) * 0.35\n sample.upper.x = rest.lean + Math.max(0, wave) * 0.08\n rest.arms.forEach((arm, index) => (sample.arms[index] = { elbow: arm.elbow + wave * 0.2 }))\n return sample\n }\n if (profile.crawl) {\n rest.arms.forEach((arm, index) => {\n const wave = index ? sine : -sine\n sample.arms[index] = { shoulder: arm.shoulder + wave * 0.35, elbow: arm.elbow - Math.max(0, wave) * 0.6 }\n })\n sample.upper.z = sine * 0.06\n return sample\n }\n if (profile.idle) {\n const scare = Math.max(0, Math.sin(time * 0.9 + phase))\n sample.upper.x = rest.lean - scare * 0.18\n sample.head.x = rest.headX - scare * 0.25\n rest.arms.forEach((arm, index) => (sample.arms[index] = { shoulder: arm.shoulder + scare * 0.25 }))\n return sample\n }\n rest.legs.forEach((leg, index) => {\n if (leg.lost) return\n const wave = index ? -sine : sine\n if (profile.drag && index === 1) return void (sample.legs[index] = { hip: leg.hip + wave * swing * 0.35, knee: leg.knee })\n sample.legs[index] = { hip: leg.hip + wave * swing, knee: leg.knee + Math.max(0, index ? cosine : -cosine) * kneeBend }\n })\n rest.arms.forEach((arm, index) => (sample.arms[index] = { shoulder: arm.shoulder + (index ? sine : -sine) * (profile.arm || 0.1) }))\n sample.hipY = rest.hipY - Math.abs(cosine) * (profile.bob || 0.02)\n sample.upper.y = sine * 0.06\n sample.upper.z = (profile.sway || 0) * sine + (profile.drag ? 0.04 : 0)\n if (profile.stalk) sample.upper.x = rest.lean + sine * 0.04\n if (profile.sniff) sample.head.y = Math.sin(time * 3.1 + phase) * 0.35\n return sample\n}\n","import { CASCADE } from './profile'\nimport type { CascadeJoint } from './profile'\n\n/** One joint moving toward its target: it covers `dt · rate` of the distance each step (never more than all of it). */\nexport const stepCascade = (current: number, target: number, dt: number, joint: CascadeJoint, rates: Readonly<Record<CascadeJoint, number>> = CASCADE): number =>\n current + (target - current) * Math.min(1, dt * rates[joint])\n\n/** Between two poses by joint name: a joint `from` does not name starts at the target (the Bestiário's `lerpPose`). */\nexport const lerpPose = <TPose extends Readonly<Record<string, number>>>(from: Partial<TPose>, to: TPose, amount: number): TPose => {\n const result: Record<string, number> = {}\n for (const name of Object.keys(to)) {\n const start = from[name]\n const end = to[name] as number\n result[name] = start === undefined ? end : (start as number) + (end - (start as number)) * amount\n }\n return result as TPose\n}\n","import gait from '../data/gait.json'\n\nexport type MoveId = keyof typeof gait.moves\nexport type MoveBlend = { gait: number; freq: number; amp: number; knee: number; bob: number; lean: number; arm: number; elb: number; crouch: number; aim: number; turn: number; grip: number }\n\n/** The human movement states the Elenco blends every frame. */\nexport const MOVES: Readonly<Record<MoveId, Readonly<MoveBlend>>> = gait.moves\n\nexport const MOVE_BLEND_RATE = 4\n\nexport const moveBlendOf = (move: MoveId): MoveBlend => ({ ...MOVES[move] })\n\n/** Moves `current` toward the target move: each number covers `dt · 4` of the distance (never past it). Mutates and returns `current`. */\nexport const blendMoves = (current: MoveBlend, target: MoveId | Readonly<MoveBlend>, dt: number): MoveBlend => {\n const goal = typeof target === 'string' ? MOVES[target] : target\n const amount = Math.min(1, dt * MOVE_BLEND_RATE)\n for (const key of Object.keys(goal) as (keyof MoveBlend)[]) current[key] += (goal[key] - current[key]) * amount\n return current\n}\n\nexport type HumanArm = { readonly side: 1 | -1; readonly hold?: boolean }\n\nexport type HumanPoseParams = {\n readonly moves: Readonly<MoveBlend>\n /** Seconds since the start. */\n readonly time: number\n /** The character's own phase offset. */\n readonly phase: number\n /** `phase + offset`: the walking cycle's angle, advanced by `dt · freq`. */\n readonly cycle: number\n /** The character's resting hunch plus the stage's. */\n readonly hunch: number\n /** The infection stage's arm raise (0 healthy .. 1 reanimated). */\n readonly armRaise: number\n /** Stage index: 3 and up adds a spine tremor, 4 is the reanimated body. */\n readonly stage: number\n /** The `prefers-reduced-motion` mode: no idle motion, no gait. */\n readonly reduced?: boolean\n readonly skirt?: boolean\n /** [right, left] as built: side and whether the hand holds an item. */\n readonly arms: readonly [HumanArm, HumanArm]\n /** [left, right] leg sides. */\n readonly legSides: readonly [1 | -1, 1 | -1]\n}\n\nexport type HumanPose = {\n readonly chestScaleY: number\n readonly hip: { readonly x: number; readonly y: number; readonly zRotation: number }\n readonly upper: { readonly x: number; readonly y: number; readonly z: number }\n readonly head: { readonly x: number; readonly y: number; readonly z: number }\n readonly legs: readonly { readonly hip: number; readonly knee: number; readonly hipZ: number }[]\n readonly arms: readonly { readonly shoulder: number; readonly shoulderZ: number; readonly elbow: number; readonly wrist: number; readonly grip: number }[]\n}\n\nconst REANIMATED_STAGE = 4\nconst TREMOR_STAGE = 3\n\n/** The blended walk of the Elenco for one frame (hips, spine, head, legs, arms), as joint targets. Pure: the caller keeps the phase and the blend. */\nexport const humanPose = (params: HumanPoseParams): HumanPose => {\n const { moves, time, phase, cycle, hunch, armRaise, stage, reduced = false, skirt = false } = params\n const zombie = stage === REANIMATED_STAGE\n const walking = reduced ? 0 : moves.gait\n const phased = phase + time\n const shift = reduced ? 0 : Math.sin(time * 0.45 + phase) * (1 - walking) * (1 - moves.aim)\n const upperX = hunch + moves.crouch * 0.15 + (stage >= TREMOR_STAGE && !reduced ? Math.sin(phased * 2.3) * 0.03 : 0)\n const upperY = walking * Math.sin(cycle - 0.35) * (0.08 + moves.arm * 0.12) - moves.aim * 0.35 + moves.turn * 0.25\n const upperZ = -shift * 0.025 + walking * Math.sin(cycle - 0.35) * 0.02 + (zombie ? 0.05 + Math.sin(cycle * 0.5) * 0.06 * walking : 0)\n const legs = params.legSides.map((side, index) => {\n const legCycle = cycle + (index ? Math.PI : 0)\n const amplitude = moves.amp * (zombie && index === 0 ? 0.45 : 1) * (skirt ? 0.75 : 1)\n return {\n hip: -walking * Math.sin(legCycle) * amplitude - moves.crouch * 0.95 + (zombie && !walking ? (index ? -0.1 : 0.08) : 0),\n knee:\n walking * (Math.max(0, Math.cos(legCycle)) * moves.knee * (zombie && index === 0 ? 0.3 : 1) + 0.06) +\n moves.crouch * 1.55 +\n (1 - walking) * (0.03 + Math.max(0, shift * (index ? 1 : -1)) * 0.18),\n hipZ: side * (0.02 + moves.aim * 0.1 + moves.crouch * 0.06),\n }\n })\n const arms = params.arms.map(({ side, hold = false }, index) => {\n const raise = armRaise * (hold && !zombie ? 0.2 : 1)\n const swing = cycle - 0.25\n const shoulderX =\n (hold ? -0.2 : 0) -\n raise * (zombie ? 1.12 : 1.3) -\n side * Math.sin(swing) * moves.arm * walking * (zombie ? 0.3 : 1) +\n (reduced || walking ? 0 : Math.sin(phased * 1.6 + side) * 0.04) +\n (zombie && !reduced ? Math.sin(phased * 3 + side * 2) * 0.08 : 0)\n const aimX = index === 0 ? -1.45 : -1.32\n return {\n shoulder: shoulderX * (1 - moves.aim) + aimX * moves.aim,\n shoulderZ: side * (0.07 + (zombie ? 0.1 : 0)) * (1 - moves.aim) - side * 0.32 * moves.aim,\n elbow: zombie ? -0.18 : -((moves.elb + (hold ? 0.25 : 0) + walking * Math.max(0, side * Math.sin(swing - 0.3)) * 0.3) * (1 - moves.aim) + (index === 0 ? 0.15 : 0.55) * moves.aim),\n wrist: reduced ? 0 : -walking * Math.sin(swing - 0.6) * 0.15 * side * (1 - moves.aim),\n grip: (hold ? 1.25 : moves.grip) * (zombie ? 0.5 : 1),\n }\n })\n const headY = (reduced ? 0 : Math.sin(phased * 0.5) * 0.25 * (1 - walking) * (1 - moves.aim) * (zombie ? 0.3 : 1)) - upperY * 0.75 * (1 - moves.turn) + moves.turn * 0.45 + moves.aim * 0.3\n return {\n chestScaleY: 1 + (reduced ? 0 : Math.sin(phased * (1.6 + moves.freq * 0.12)) * (0.012 + moves.freq * 0.0012)),\n hip: { x: shift * 0.025 + walking * Math.sin(cycle) * 0.018, y: -walking * moves.bob * Math.abs(Math.sin(cycle)) - moves.crouch * 0.26, zRotation: shift * 0.02 - walking * Math.sin(cycle) * 0.022 },\n upper: { x: upperX, y: upperY, z: upperZ },\n head: { x: -hunch * 0.6 - moves.crouch * 0.12 + (zombie ? 0.15 : 0) + walking * Math.sin(cycle * 2 - 0.6) * 0.02, y: headY, z: (zombie ? 0.22 : 0) - upperZ * 0.6 },\n legs,\n arms,\n }\n}\n\n/** A leg that cannot carry weight (limp): the swing shrinks to 30%, the knee straightens, the spine leans toward the good leg. */\nexport const LIMP = { swing: 0.3, knee: 0.05, lean: 0.07 } as const\n","/** Prone crawl on the arms (the Elenco's leg-less body): joint targets at `time`; `figTilt` is the body's tilt target, which the caller approaches at `dt · 4`. */\nexport type CrawlPose = {\n readonly figTilt: number\n readonly hipY: number\n readonly hipZRotation: number\n readonly upper: { readonly x: number; readonly y: number }\n readonly headX: number\n readonly arms: readonly { readonly shoulder: number; readonly shoulderZ: number; readonly elbow: number }[]\n readonly legs: readonly { readonly hip: number; readonly knee: number }[]\n}\n\nexport const CRAWL_TILT_RATE = 4\nexport const DEAD_TILT_RATE = 3\n\nexport const crawlPose = (time: number, phase: number, sides: readonly [1 | -1, 1 | -1]): CrawlPose => {\n const cycle = time * 2.2 + phase\n const wave = Math.sin(cycle)\n return {\n figTilt: 1.38,\n hipY: 0.2 + Math.abs(wave) * 0.02,\n hipZRotation: wave * 0.05,\n upper: { x: 0, y: wave * 0.12 },\n headX: -0.95,\n arms: sides.map((side) => ({ shoulder: -2.55 + side * wave * 0.45, shoulderZ: side * 0.25, elbow: -0.35 - Math.max(0, -side * wave) * 0.6 })),\n legs: [\n { hip: 0.1, knee: 0 },\n { hip: 0.12 + wave * 0.08, knee: 0.25 },\n ],\n }\n}\n\nexport type DeadPose = {\n readonly figTilt: number\n readonly hipY: number\n readonly headY: number\n readonly arms: readonly { readonly shoulder: number; readonly shoulderZ: number; readonly elbow: number }[]\n readonly legs: readonly { readonly hip: number; readonly hipZ: number; readonly knee: number }[]\n}\n\n/** A body on the ground (the Elenco's death pose); the caller approaches `figTilt` at `dt · 3`. */\nexport const deadPose = (armSides: readonly [1 | -1, 1 | -1]): DeadPose => ({\n figTilt: -1.45,\n hipY: 0.22,\n headY: 0.5,\n arms: armSides.map((side) => ({ shoulder: -0.2, shoulderZ: side * 1.1, elbow: -0.3 })),\n legs: [-0.15, 0.15].map((hipZ) => ({ hip: 0, hipZ, knee: 0.1 })),\n})\n","export type ConditionPhase = {\n readonly id: string\n /** When the phase starts, in the timeline's units (hours, or seconds on an accelerated clock). The first phase starts at 0. */\n readonly startsAt: number\n /** Numbers the phase drives (skin tint, hunch, arm raise, ...), by name. */\n readonly effects?: Readonly<Record<string, number>>\n}\n\nexport type ConditionOptions = {\n readonly phases: readonly ConditionPhase[]\n /** Timeline units per real second: 1 on a clock already in seconds (the accelerated preset), 1/3600 for hours. Default 1. */\n readonly unitsPerSecond?: number\n /** Interpolate effects toward the next phase instead of stepping. Default false. */\n readonly blend?: boolean\n}\n\nexport type ConditionSample = {\n readonly index: number\n readonly phase: ConditionPhase\n /** 0..1 inside the current phase (1 on the last one). */\n readonly progress: number\n readonly effects: Readonly<Record<string, number>>\n readonly isFinal: boolean\n}\n\nexport type ConditionTimeline = {\n readonly elapsed: number\n /** Advances the clock by `seconds` of real time. */\n advance(seconds: number): ConditionSample\n /** Jumps the clock to `units` of the timeline. */\n seek(units: number): ConditionSample\n sample(): ConditionSample\n reset(): void\n}\n\nconst phaseIndexAt = (phases: readonly ConditionPhase[], units: number): number => {\n let found = 0\n phases.forEach((phase, index) => {\n if (units >= phase.startsAt) found = index\n })\n return found\n}\n\nconst mixEffects = (from: ConditionPhase['effects'], to: ConditionPhase['effects'], amount: number): Record<string, number> => {\n const result: Record<string, number> = {}\n for (const name of new Set([...Object.keys(from ?? {}), ...Object.keys(to ?? {})])) {\n const start = from?.[name] ?? 0\n result[name] = start + ((to?.[name] ?? 0) - start) * amount\n }\n return result\n}\n\n/** A condition that moves through ordered phases over time (an infection: well, fever, delirium, reanimated). Generic: phases and effects are data. */\nexport const createConditionTimeline = (options: ConditionOptions): ConditionTimeline => {\n const { phases, unitsPerSecond = 1, blend = false } = options\n if (phases.length === 0) throw new Error('createConditionTimeline: at least one phase is required')\n let units = 0\n const sample = (): ConditionSample => {\n const index = phaseIndexAt(phases, units)\n const phase = phases[index] as ConditionPhase\n const next = phases[index + 1]\n const progress = next ? Math.min(1, (units - phase.startsAt) / (next.startsAt - phase.startsAt)) : 1\n const effects = blend && next ? mixEffects(phase.effects, next.effects, progress) : { ...phase.effects }\n return { index, phase, progress, effects, isFinal: !next }\n }\n return {\n get elapsed() {\n return units\n },\n advance(seconds) {\n units += seconds * unitsPerSecond\n return sample()\n },\n seek(target) {\n units = Math.max(0, target)\n return sample()\n },\n sample,\n reset() {\n units = 0\n },\n }\n}\n","{\n \"variance\": {\n \"height\": {\n \"gaussianSpread\": 0.09,\n \"min\": 0.9,\n \"max\": 1.1\n },\n \"buildBands\": [\n {\n \"below\": 0.3,\n \"base\": 0.85,\n \"range\": 0.1\n },\n {\n \"below\": 0.8,\n \"base\": 0.95,\n \"range\": 0.13\n },\n {\n \"base\": 1.08,\n \"range\": 0.17\n }\n ],\n \"buildSpeed\": {\n \"lean\": 1.05,\n \"heavy\": 0.9\n },\n \"buildHealth\": {\n \"lean\": 0.9,\n \"heavy\": 1.15\n },\n \"speedJitter\": {\n \"base\": 0.92,\n \"range\": 0.16\n },\n \"wanderJitter\": {\n \"base\": 0.8,\n \"range\": 0.4\n },\n \"runnerAgeClamp\": 1,\n \"variantCount\": {\n \"walker\": 4,\n \"runner\": 3,\n \"crawler\": 2,\n \"brute\": 2\n },\n \"variantSeedBase\": 7000\n },\n \"civilianColors\": [\n \"6D5A4A\",\n \"4D5D6B\",\n \"7A3B33\",\n \"5B6B4A\",\n \"8A7A5A\",\n \"3E4A5C\",\n \"6A4A6A\",\n \"9A8A70\",\n \"40403A\"\n ],\n \"corpses\": {\n \"max\": 400,\n \"lifeSeconds\": 900\n }\n}\n","import appearance from '../data/appearance.json'\n\nconst { variance } = appearance\n\nexport type BuildClass = 'lean' | 'average' | 'heavy'\n\n/** What `zSpawn` draws for a body: height, width, how it builds up and the speed jitters. Every field comes from the stream, in the game's order. */\nexport type BodyVariance = {\n readonly height: number\n readonly build: number\n readonly buildClass: BuildClass\n /** Multiplies the chase speed: the build factor times a 0.92 .. 1.08 jitter. */\n readonly speedFactor: number\n /** Multiplies the wander speed: 0.8 .. 1.2. */\n readonly wanderFactor: number\n /** Multiplies the health: 0.9 lean, 1.15 heavy. */\n readonly healthFactor: number\n}\n\nexport type VarianceScale = { readonly height?: number; readonly build?: number }\n\nconst clamp = (value: number, low: number, high: number): number => Math.min(high, Math.max(low, value))\n\n/**\n * One body's variance from `random`, drawing exactly what the game's `zSpawn` draws after the type, age and outfit picks:\n * three draws for the height (a gaussian), one for the build band plus one inside it, one for the speed and one for the wander speed.\n * `scale` is the type's own scale (a brute's 1.42) and `build` its width factor.\n */\nexport const drawBodyVariance = (random: () => number, scale: VarianceScale = {}): BodyVariance => {\n const spread = (random() + random() + random() - 1.5) * variance.height.gaussianSpread\n const height = clamp(1 + spread, variance.height.min, variance.height.max) * (scale.height ?? 1)\n const band = random()\n const bands = variance.buildBands as readonly { below?: number; base: number; range: number }[]\n const found = bands.find((candidate) => candidate.below !== undefined && band < candidate.below) ?? (bands[bands.length - 1] as { base: number; range: number })\n const { base, range } = found\n const build = (base + random() * range) * (scale.build ?? 1)\n const buildClass: BuildClass = band < 0.3 ? 'lean' : band >= 0.8 ? 'heavy' : 'average'\n const speedBuild = buildClass === 'lean' ? variance.buildSpeed.lean : buildClass === 'heavy' ? variance.buildSpeed.heavy : 1\n const healthBuild = buildClass === 'lean' ? variance.buildHealth.lean : buildClass === 'heavy' ? variance.buildHealth.heavy : 1\n return {\n height,\n build,\n buildClass,\n speedFactor: speedBuild * (variance.speedJitter.base + random() * variance.speedJitter.range),\n wanderFactor: variance.wanderJitter.base + random() * variance.wanderJitter.range,\n healthFactor: healthBuild,\n }\n}\n\n/** Variants baked per type (the game's `nv`): 4 walkers, 3 runners, 2 crawlers and brutes, 1 for the rest. */\nexport const variantCountFor = (typeId: string): number => (variance.variantCount as Readonly<Record<string, number>>)[typeId] ?? 1\n\n/** The seed of variant `variant` of the type at `typeIndex` (the game's ZVAR rule: `7000 + c·101 + v·13`). */\nexport const variantSeed = (typeIndex: number, variant: number): number => variance.variantSeedBase + typeIndex * 101 + variant * 13\n\n/** The decay each variant is baked at: 1, 2, 1, 2. */\nexport const variantDecay = (variant: number): number => (variant % 2 === 0 ? 1 : 2)\n","/** The colour and style pools of the Bestiário v17 builder, in the order its random stream picks from them. */\nexport const SKIN_TONES = [0xf1c9a5, 0xe0ac80, 0xc68c62, 0xa8714a, 0x8a5a3a, 0x5e3b26] as const\nexport const TOP_COLORS = [0x4a6f96, 0x8e3b3b, 0x5d4a3a, 0x4f7a43, 0x6b6f78, 0x3f5f3a, 0x5a4a6e, 0x8a6a3a, 0xb8b2a2, 0x2c2c30, 0x9a4a2a, 0x2f5d63, 0xc9a94a, 0x7a2e4a, 0xd8d4c8, 0x3a4a6a] as const\nexport const PANTS_COLORS = [0x2c3340, 0x1f2228, 0x4a4030, 0x5a5f66, 0x3a4a6a, 0x6a5a40, 0x2a3a2a] as const\nexport const SLEEVES = ['short', 'short', 'long', 'tank'] as const\nexport const HAIR_STYLES_FEMALE = ['long', 'long', 'bun', 'short', 'afro', 'bald'] as const\nexport const HAIR_STYLES_MALE = ['short', 'short', 'buzz', 'bald', 'afro', 'long'] as const\nexport const CAP_COLORS = [0x8e3b3b, 0x2c2c30, 0x3a4a6a, 0xc9a94a] as const\nexport const BAG_COLORS = [0x3a4a3a, 0x5a2a24, 0x2c3340] as const\nexport const HAIR_COLORS = [0x1a1410, 0x2a1e16, 0x3b2c20, 0x6a4a2a, 0xb08a50, 0x7a2a1a] as const\nexport const SHOE_COLORS = [0x1d1f22, 0x3a2a1a, 0xb8b4a8, 0x4a1a1a] as const\n/** Uniform bodies (the crowd's baked variants): skin by decay, shirt by type index. */\nexport const DECAY_SKIN = [0xcdbba8, 0x94a084, 0x7b744a, 0x8c7c5e] as const\nexport const UNIFORM_SHIRTS = [0x4a6f96, 0x8e3b3b, 0x5d4a3a, 0x4f7a43, 0x6b6f78, 0x3f5f3a, 0x5a4a6e, 0x8a6a3a] as const\nexport const UNIFORM_PANTS = 0x2c3340\nexport const UNIFORM_SHOES = 0x1d1f22\nexport const SKIN_DECAY_BLEND = [0.45, 0.65, 0.8, 0.88] as const\nexport const GRAY = 0x4a4a46\nexport const RED = 0x7a120c\nexport const BLOOD_COLORS = [0x9e1b12, 0x6e1410, 0x4a2a18, 0x1c1612] as const\nexport const OLD_HAIR = 0x8a8780\n","import { createRng } from '../damage/points'\n\nimport {\n BAG_COLORS,\n CAP_COLORS,\n DECAY_SKIN,\n HAIR_COLORS,\n HAIR_STYLES_FEMALE,\n HAIR_STYLES_MALE,\n OLD_HAIR,\n PANTS_COLORS,\n SHOE_COLORS,\n SKIN_TONES,\n SLEEVES,\n TOP_COLORS,\n UNIFORM_PANTS,\n UNIFORM_SHIRTS,\n UNIFORM_SHOES,\n} from './palette'\n\nexport type HairStyle = (typeof HAIR_STYLES_FEMALE)[number] | (typeof HAIR_STYLES_MALE)[number]\n\nexport type OutfitLook = { readonly cloth?: number; readonly pants?: number; readonly hat?: string }\n\nexport type AppearanceParams = {\n readonly seed: number\n /** The look of an outfit (police, military ...): its colours replace the draws, so the stream does not spend them. */\n readonly outfit?: OutfitLook\n /** A baked crowd variant: no random look, fixed skin, shirt by `typeIndex`, short hair. */\n readonly uniform?: boolean\n readonly typeIndex?: number\n readonly clothIndex?: number\n /** Forces the sex; unset draws it (42% female). */\n readonly female?: boolean\n /** False for bodies that are never female (a brute): the draw is skipped. */\n readonly allowFemale?: boolean\n readonly tone?: number\n readonly hairStyle?: HairStyle\n readonly hairColor?: number\n /** The type's own look: wet bodies have long hair, charred ones are bald. */\n readonly wet?: boolean\n readonly charred?: boolean\n /** A living person: no bag, no tear. */\n readonly human?: boolean\n /** 0 fresh-dead, 1 normal, 2 old (grey hair). */\n readonly life?: number\n}\n\nexport type AppearanceTraits = {\n readonly female: boolean\n readonly tone: number\n readonly topColor: number\n readonly pantsColor: number\n readonly sleeve: string\n readonly hair: string\n readonly headWidth: number\n readonly headHeight: number\n readonly jaw: number\n readonly nose: number\n readonly beard: boolean\n readonly glasses: boolean\n readonly cap: boolean\n readonly capColor: number\n readonly bag: boolean\n readonly bagColor: number\n readonly torn: boolean\n readonly apron: boolean\n readonly hairColor: number\n readonly shoeColor: number\n}\n\nexport type DrawnAppearance = {\n readonly traits: AppearanceTraits\n /** The stream, positioned after the look: the body builder keeps drawing from it (the hair of a decrepit body). */\n readonly random: () => number\n}\n\n/** The seed of the blood stream (the same drips on every level of detail). */\nexport const BLOOD_SEED_OFFSET = 99\n\nexport const createBloodStream = (seed: number): (() => number) => createRng(seed + BLOOD_SEED_OFFSET)\n\nconst FEMALE_SHARE = 0.42\nconst BEARD_SHARE = 0.25\nconst GLASSES_SHARE = 0.12\nconst CAP_SHARE = 0.12\nconst BAG_SHARE = 0.15\nconst TORN_SHARE = 0.35\nconst APRON_SHARE = 0.05\n\n/**\n * A person's look from a seed, drawing in exactly the order the Bestiário v17 builder draws from its `VR` stream, including the draws a\n * short-circuit skips (no beard roll for a woman, no cap roll under a hat). Returns the stream so the builder can continue from it.\n */\nexport const drawAppearance = (params: AppearanceParams): DrawnAppearance => {\n const { seed, outfit = {}, uniform = false, typeIndex = 0, human = false, life = 1 } = params\n const random = createRng(seed)\n const pick = <T>(options: readonly T[]): T => options[Math.floor(random() * options.length)] as T\n const female = !uniform && (params.allowFemale ?? true) && (params.female ?? random() < FEMALE_SHARE)\n const tone = params.tone ?? (uniform ? (DECAY_SKIN[0] as number) : pick(SKIN_TONES))\n const topColor = outfit.cloth ?? (uniform ? (UNIFORM_SHIRTS[(params.clothIndex ?? typeIndex) % UNIFORM_SHIRTS.length] as number) : pick(TOP_COLORS))\n const pantsColor = outfit.pants ?? (uniform ? UNIFORM_PANTS : pick(PANTS_COLORS))\n const look = uniform ? uniformLook() : drawLook({ random, pick, female, outfit, human, params })\n const hairColor = params.hairColor ?? (life === 2 ? OLD_HAIR : pick(HAIR_COLORS))\n const shoeColor = uniform ? UNIFORM_SHOES : pick(SHOE_COLORS)\n return { traits: { female, tone, topColor, pantsColor, ...look, hairColor, shoeColor }, random }\n}\n\ntype Look = Omit<AppearanceTraits, 'female' | 'tone' | 'topColor' | 'pantsColor' | 'hairColor' | 'shoeColor'>\n\nconst uniformLook = (): Look => ({\n sleeve: 'short',\n hair: 'short',\n headWidth: 1,\n headHeight: 1,\n jaw: 1,\n nose: 1,\n beard: false,\n glasses: false,\n cap: false,\n capColor: 0,\n bag: false,\n bagColor: 0,\n torn: false,\n apron: false,\n})\n\ntype DrawLookParams = {\n readonly random: () => number\n readonly pick: <T>(options: readonly T[]) => T\n readonly female: boolean\n readonly outfit: OutfitLook\n readonly human: boolean\n readonly params: AppearanceParams\n}\n\nconst drawLook = ({ random, pick, female, outfit, human, params }: DrawLookParams): Look => {\n const sleeve = outfit.cloth ? 'long' : pick(SLEEVES)\n const hair = params.hairStyle ?? (params.wet ? 'long' : params.charred ? 'bald' : pick(female ? HAIR_STYLES_FEMALE : HAIR_STYLES_MALE))\n const headWidth = 1 + (random() - 0.5) * 0.16\n const headHeight = 1 + (random() - 0.5) * 0.14\n const jaw = 1 + (random() - 0.5) * 0.3\n const nose = 1 + (random() - 0.5) * 0.5\n const beard = !female && random() < BEARD_SHARE\n const glasses = random() < GLASSES_SHARE\n const cap = !outfit.hat && random() < CAP_SHARE\n const capColor = pick(CAP_COLORS)\n const bag = random() < BAG_SHARE && !human\n const bagColor = pick(BAG_COLORS)\n const torn = random() < TORN_SHARE && !human\n const apron = random() < APRON_SHARE\n return { sleeve, hair, headWidth, headHeight, jaw, nose, beard, glasses, cap, capColor, bag, bagColor, torn, apron }\n}\n","import { lerpPose } from '../gait/cascade'\n\n/** One key of a clip: the time in seconds and the joint targets by name (the names of the rich body's `setPose`; a clip may add channels of its own, such as `x` or `run`). */\nexport type PoseKey = { t: number; pose: Record<string, number> }\n\n/** What a clip says happens at a time: `impact` (\"the blow lands now\"), `phase` (a label for the screen), or any type a game defines. */\nexport type PoseClipEvent = { t: number; type: string; data?: Record<string, unknown> }\n\n/** Which joints a clip drives: `upper` leaves the legs to the gait, `lower` leaves the trunk, head and arms, `full` sets everything. */\nexport type PoseClipChannels = 'full' | 'upper' | 'lower'\n\nexport type PoseClip = {\n id: string\n duration: number\n loop?: boolean\n keys: PoseKey[]\n events?: PoseClipEvent[]\n channels?: PoseClipChannels\n /** Where the clip was ported from (file and variable), for the diff against the team page. */\n source?: Record<string, unknown>\n}\n\n/**\n * The Bestiário's `sample(K, t)`: finds the segment of two keys, clamps the fraction to [0, 1], eases it with smoothstep `k·k·(3 − 2k)` and\n * blends the two poses by joint name (`lerpPose`). Before the first key it holds the first segment's start, after the last it holds the end.\n */\nexport const samplePoseClip = (clip: Pick<PoseClip, 'keys'>, time: number): Record<string, number> => {\n const keys = clip.keys\n if (keys.length === 0) return {}\n if (keys.length === 1) return { ...keys[0]!.pose }\n let index = 0\n while (index < keys.length - 2 && time > keys[index + 1]!.t) index++\n const a = keys[index]!\n const b = keys[index + 1]!\n const k = Math.min(1, Math.max(0, (time - a.t) / (b.t - a.t)))\n const eased = k * k * (3 - 2 * k)\n return lerpPose(a.pose, b.pose, eased)\n}\n\n/** The events a clip fires while the clock goes from `from` (excluded) to `to` (included), in time order. */\nexport const clipEventsBetween = (clip: Pick<PoseClip, 'events'>, from: number, to: number): PoseClipEvent[] =>\n (clip.events ?? []).filter((event) => event.t > from && event.t <= to).sort((x, y) => x.t - y.t)\n\n/** The names of the joints a channel set drives, from the names `PoseTargets` of the rich animator knows. */\nexport const POSE_CHANNEL_JOINTS: Readonly<Record<PoseClipChannels, readonly string[] | undefined>> = {\n full: undefined,\n upper: ['lean', 'twist', 'side', 'headX', 'headY', 'headZ', 'armR', 'armL', 'elbR', 'elbL', 'armRz', 'armLz'],\n lower: ['drop', 'legL', 'legR', 'kneeL', 'kneeR'],\n}\n\n/** Keeps from a sampled pose only the joints of the channel set (`full` keeps everything, including extra channels such as `x`). */\nexport const filterPoseChannels = (pose: Record<string, number>, channels: PoseClipChannels = 'full'): Record<string, number> => {\n const allowed = POSE_CHANNEL_JOINTS[channels]\n if (!allowed) return pose\n const out: Record<string, number> = {}\n for (const name of allowed) if (pose[name] !== undefined) out[name] = pose[name] as number\n return out\n}\n\n/** Joints that swap with their opposite when a clip is mirrored, and the channels that change sign (side, twist and the sideways turns). */\nconst MIRROR_PAIRS: ReadonlyArray<readonly [string, string]> = [['armR', 'armL'], ['elbR', 'elbL'], ['armRz', 'armLz'], ['legR', 'legL'], ['kneeR', 'kneeL']]\nconst MIRROR_NEGATED: ReadonlySet<string> = new Set(['side', 'twist', 'headY', 'headZ'])\n\n/** The clip as seen in a mirror: left and right swap and the sideways channels change sign; the times, the events and the duration stay, so the impact falls at the same second. */\nexport const mirrorPoseClip = (clip: PoseClip, id: string): PoseClip => ({\n ...clip,\n id,\n keys: clip.keys.map((key) => {\n const pose: Record<string, number> = {}\n for (const [name, value] of Object.entries(key.pose)) pose[name] = MIRROR_NEGATED.has(name) ? -value : value\n for (const [a, b] of MIRROR_PAIRS) {\n const va = key.pose[a]\n const vb = key.pose[b]\n const sign = a === 'armRz' ? -1 : 1 // the sideways swing of an arm opens to the other side\n if (vb !== undefined) pose[a] = sign * vb\n else delete pose[a]\n if (va !== undefined) pose[b] = sign * va\n else delete pose[b]\n }\n return { t: key.t, pose }\n }),\n ...(clip.events ? { events: clip.events.map((event) => ({ ...event })) } : {}),\n})\n","{\n \"clips\": [\n {\n \"id\": \"grabbed_bitten_human\",\n \"source\": {\n \"file\": \"site/pages/zumbis-personagens/bestiario.html\",\n \"scene\": \"ataque (Agarrão e mordida)\",\n \"variable\": \"HK\"\n },\n \"duration\": 8,\n \"loop\": false,\n \"channels\": \"full\",\n \"keys\": [\n {\n \"t\": 0,\n \"pose\": {\n \"lean\": 0,\n \"headY\": 0,\n \"armL\": -0.1,\n \"armR\": 0.05,\n \"elbL\": -0.2,\n \"elbR\": -0.2,\n \"drop\": 0,\n \"kneeL\": 0.05,\n \"kneeR\": 0.05,\n \"legL\": -0.05,\n \"legR\": 0.05,\n \"headX\": 0\n }\n },\n {\n \"t\": 1.5,\n \"pose\": {\n \"lean\": -0.1,\n \"headY\": -0.6,\n \"armL\": -0.1,\n \"armR\": 0.05,\n \"elbL\": -0.2,\n \"elbR\": -0.2,\n \"drop\": 0,\n \"kneeL\": 0.05,\n \"kneeR\": 0.05,\n \"legL\": -0.05,\n \"legR\": 0.05,\n \"headX\": -0.1\n }\n },\n {\n \"t\": 2.1,\n \"pose\": {\n \"lean\": -0.3,\n \"headY\": -0.2,\n \"armL\": -1.3,\n \"armR\": -1.2,\n \"elbL\": -1.4,\n \"elbR\": -1.5,\n \"drop\": -0.04,\n \"kneeL\": 0.25,\n \"kneeR\": 0.2,\n \"legL\": -0.3,\n \"legR\": 0.25,\n \"headX\": -0.25\n }\n },\n {\n \"t\": 3.6,\n \"pose\": {\n \"lean\": -0.35,\n \"headY\": 0.3,\n \"armL\": -1.5,\n \"armR\": -1.0,\n \"elbL\": -0.6,\n \"elbR\": -1.8,\n \"drop\": -0.05,\n \"kneeL\": 0.3,\n \"kneeR\": 0.2,\n \"legL\": -0.4,\n \"legR\": 0.35,\n \"headX\": -0.2\n }\n },\n {\n \"t\": 4.3,\n \"pose\": {\n \"lean\": -0.2,\n \"headY\": 0.7,\n \"headZ\": -0.5,\n \"armL\": -0.6,\n \"armR\": -1.9,\n \"elbL\": -0.4,\n \"elbR\": -1.2,\n \"drop\": -0.06,\n \"kneeL\": 0.3,\n \"kneeR\": 0.3,\n \"legL\": -0.3,\n \"legR\": 0.3,\n \"headX\": -0.3\n }\n },\n {\n \"t\": 5.6,\n \"pose\": {\n \"lean\": 0.55,\n \"headY\": 0.4,\n \"headZ\": -0.3,\n \"armL\": -0.3,\n \"armR\": -0.5,\n \"elbL\": -0.6,\n \"elbR\": -0.8,\n \"drop\": -0.5,\n \"kneeL\": 1.9,\n \"kneeR\": 1.7,\n \"legL\": -1.1,\n \"legR\": -0.9,\n \"headX\": 0.3\n }\n },\n {\n \"t\": 8,\n \"pose\": {\n \"lean\": 0.6,\n \"headY\": 0.4,\n \"headZ\": -0.3,\n \"armL\": -0.25,\n \"armR\": -0.45,\n \"elbL\": -0.6,\n \"elbR\": -0.8,\n \"drop\": -0.52,\n \"kneeL\": 1.95,\n \"kneeR\": 1.75,\n \"legL\": -1.1,\n \"legR\": -0.95,\n \"headX\": 0.4\n }\n }\n ],\n \"events\": [\n {\n \"t\": 0,\n \"type\": \"phase\",\n \"data\": {\n \"label\": \"pose_clip.grab_bite.phase.approach\"\n }\n },\n {\n \"t\": 1.7,\n \"type\": \"phase\",\n \"data\": {\n \"label\": \"pose_clip.grab_bite.phase.pounce\"\n }\n },\n {\n \"t\": 2.1,\n \"type\": \"phase\",\n \"data\": {\n \"label\": \"pose_clip.grab_bite.phase.grab\"\n }\n },\n {\n \"t\": 4.3,\n \"type\": \"phase\",\n \"data\": {\n \"label\": \"pose_clip.grab_bite.phase.bite\"\n }\n },\n {\n \"t\": 5.6,\n \"type\": \"phase\",\n \"data\": {\n \"label\": \"pose_clip.grab_bite.phase.fall\"\n }\n },\n {\n \"t\": 4.4,\n \"type\": \"impact\",\n \"data\": {\n \"kind\": \"bite\",\n \"source\": \"bite.visible=T>4.4 in the scene's step()\"\n }\n }\n ]\n },\n {\n \"id\": \"grab_bite_zombie\",\n \"source\": {\n \"file\": \"site/pages/zumbis-personagens/bestiario.html\",\n \"scene\": \"ataque (Agarrão e mordida)\",\n \"variable\": \"ZK\"\n },\n \"duration\": 8,\n \"loop\": false,\n \"channels\": \"full\",\n \"keys\": [\n {\n \"t\": 0,\n \"pose\": {\n \"x\": -6,\n \"lean\": 0.75,\n \"armL\": -1.35,\n \"armR\": -1.05,\n \"elbL\": -0.08,\n \"elbR\": -0.12,\n \"headX\": -0.55,\n \"drop\": -0.1,\n \"run\": 1\n }\n },\n {\n \"t\": 1.7,\n \"pose\": {\n \"x\": -0.9,\n \"lean\": 0.75,\n \"armL\": -1.35,\n \"armR\": -1.05,\n \"elbL\": -0.08,\n \"elbR\": -0.12,\n \"headX\": -0.55,\n \"drop\": -0.1,\n \"run\": 1\n }\n },\n {\n \"t\": 2.1,\n \"pose\": {\n \"x\": -0.32,\n \"lean\": 0.45,\n \"armL\": -1.65,\n \"armR\": -1.6,\n \"elbL\": -0.25,\n \"elbR\": -0.3,\n \"headX\": -0.3,\n \"drop\": -0.08,\n \"legL\": -0.6,\n \"legR\": 0.4,\n \"kneeL\": 0.5,\n \"kneeR\": 0.6,\n \"run\": 0\n }\n },\n {\n \"t\": 3.6,\n \"pose\": {\n \"x\": -0.2,\n \"lean\": 0.35,\n \"armL\": -1.5,\n \"armR\": -1.45,\n \"elbL\": -1.1,\n \"elbR\": -1.2,\n \"headX\": -0.2,\n \"drop\": -0.06,\n \"legL\": -0.4,\n \"legR\": 0.3,\n \"kneeL\": 0.4,\n \"kneeR\": 0.4,\n \"run\": 0\n }\n },\n {\n \"t\": 4.3,\n \"pose\": {\n \"x\": -0.1,\n \"lean\": 0.5,\n \"armL\": -1.4,\n \"armR\": -1.3,\n \"elbL\": -1.5,\n \"elbR\": -1.5,\n \"headX\": 0.35,\n \"headY\": 0.35,\n \"drop\": -0.08,\n \"legL\": -0.35,\n \"legR\": 0.3,\n \"kneeL\": 0.4,\n \"kneeR\": 0.4,\n \"run\": 0\n }\n },\n {\n \"t\": 5.6,\n \"pose\": {\n \"x\": 0,\n \"lean\": 0.95,\n \"armL\": -1.2,\n \"armR\": -1.0,\n \"elbL\": -1.4,\n \"elbR\": -1.3,\n \"headX\": 0.5,\n \"headY\": 0.3,\n \"drop\": -0.45,\n \"legL\": -1.2,\n \"legR\": -0.8,\n \"kneeL\": 1.8,\n \"kneeR\": 1.5,\n \"run\": 0\n }\n },\n {\n \"t\": 8,\n \"pose\": {\n \"x\": 0,\n \"lean\": 1.0,\n \"armL\": -1.15,\n \"armR\": -0.95,\n \"elbL\": -1.4,\n \"elbR\": -1.3,\n \"headX\": 0.55,\n \"headY\": 0.3,\n \"drop\": -0.47,\n \"legL\": -1.2,\n \"legR\": -0.8,\n \"kneeL\": 1.85,\n \"kneeR\": 1.5,\n \"run\": 0\n }\n }\n ],\n \"events\": [\n {\n \"t\": 0,\n \"type\": \"phase\",\n \"data\": {\n \"label\": \"pose_clip.grab_bite.phase.approach\"\n }\n },\n {\n \"t\": 1.7,\n \"type\": \"phase\",\n \"data\": {\n \"label\": \"pose_clip.grab_bite.phase.pounce\"\n }\n },\n {\n \"t\": 2.1,\n \"type\": \"phase\",\n \"data\": {\n \"label\": \"pose_clip.grab_bite.phase.grab\"\n }\n },\n {\n \"t\": 4.3,\n \"type\": \"phase\",\n \"data\": {\n \"label\": \"pose_clip.grab_bite.phase.bite\"\n }\n },\n {\n \"t\": 5.6,\n \"type\": \"phase\",\n \"data\": {\n \"label\": \"pose_clip.grab_bite.phase.fall\"\n }\n }\n ]\n }\n ],\n \"locales\": {\n \"pt-BR\": {\n \"pose_clip.grab_bite.phase.approach\": \"1. Aproximação\",\n \"pose_clip.grab_bite.phase.pounce\": \"2. O bote\",\n \"pose_clip.grab_bite.phase.grab\": \"3. Agarrão: 3 s para se soltar\",\n \"pose_clip.grab_bite.phase.bite\": \"4. Mordida: infecção 100%\",\n \"pose_clip.grab_bite.phase.fall\": \"5. Queda\"\n },\n \"en\": {\n \"pose_clip.grab_bite.phase.approach\": \"1. Approach\",\n \"pose_clip.grab_bite.phase.pounce\": \"2. The pounce\",\n \"pose_clip.grab_bite.phase.grab\": \"3. Grab: 3 s to break free\",\n \"pose_clip.grab_bite.phase.bite\": \"4. Bite: 100% infection\",\n \"pose_clip.grab_bite.phase.fall\": \"5. The fall\"\n }\n }\n}","import data from '../presets/pose-clips.json'\n\nimport type { PoseClip } from './pose-clip'\n\nexport type PoseClipRegistry = {\n /** Adds a clip, or replaces the one with the same id. Returns the registry. */\n register(clip: PoseClip): PoseClipRegistry\n get(id: string): PoseClip | undefined\n list(): PoseClip[]\n remove(id: string): boolean\n}\n\n/** A registry of clips by id: games add or replace clips without touching the core. */\nexport const createPoseClipRegistry = (initial: readonly PoseClip[] = []): PoseClipRegistry => {\n const clips = new Map<string, PoseClip>()\n const registry: PoseClipRegistry = {\n register(clip) {\n clips.set(clip.id, clip)\n return registry\n },\n get: (id) => clips.get(id),\n list: () => [...clips.values()],\n remove: (id) => clips.delete(id),\n }\n for (const clip of initial) registry.register(clip)\n return registry\n}\n\n/** The clips ported from the Bestiário \"grab and bite\" scene (human and zombie). Phase labels are locale keys, see `POSE_CLIP_LOCALES`. */\nexport const POSE_CLIPS: readonly PoseClip[] = data.clips as PoseClip[]\n\n/** Texts of the phase labels by locale (`pt-BR` is the team's text). */\nexport const POSE_CLIP_LOCALES: Readonly<Record<string, Readonly<Record<string, string>>>> = data.locales\n","import type { PoseClipEvent } from './pose-clip'\n\ntype Triple = [number, number, number]\n\n/**\n * A hand or a foot in the camera's space (x to the right, y up, the view looks down -z), in metres and radians. `p` is the middle of the palm (the ankle for a foot) and `r` the Euler angles\n * (order XYZ) of its frame: x from the wrist to the knuckles (from the heel to the toes), y the back of the hand (the top of the foot), z the rest of the right-handed frame; a left hand is the\n * mirror image of a right one, so the same numbers describe the same grip.\n */\nexport type FirstPersonPoseKey = {\n p: Triple\n r: Triple\n /** How closed the fingers are, 0 open to 1 closed; left out, the fingers keep what the stance has. */\n grip?: number\n /** How much of the clip replaces what the hand is doing otherwise (holding a weapon, the stance), 0 none to 1 all. Default 1. */\n w?: number\n}\n\n/** One key: at `t` seconds the right hand (`R`), the left hand (`L`, or `'mirror'` for the mirror image of the right) and the right foot (`F`) are where the entries say. A side without an entry here is not driven by this key. */\nexport type FirstPersonKey = { t: number; R?: FirstPersonPoseKey; L?: FirstPersonPoseKey | 'mirror'; F?: FirstPersonPoseKey }\n\n/** A first-person animation of the hands and the foot: the counterpart of a third-person `PoseClip`, with the same events. */\nexport type FirstPersonClip = {\n id: string\n duration: number\n keys: FirstPersonKey[]\n events?: PoseClipEvent[]\n /** Where the clip was ported from, or who authored it. */\n source?: Record<string, unknown>\n}\n\n/** What a channel does at a time. `mirror` says the numbers are the right hand's and the left hand is their mirror image. */\nexport type FirstPersonSampleChannel = { p: Triple; r: Triple; grip: number | undefined; w: number; mirror: boolean }\nexport type FirstPersonSample = { R?: FirstPersonSampleChannel; L?: FirstPersonSampleChannel; F?: FirstPersonSampleChannel }\n\nconst ease = (k: number): number => k * k * (3 - 2 * k)\nconst mix = (a: number, b: number, k: number): number => a + (b - a) * k\nconst mixTriple = (a: Triple, b: Triple, k: number): Triple => [mix(a[0], b[0], k), mix(a[1], b[1], k), mix(a[2], b[2], k)]\n\ntype Track = { t: number; key: FirstPersonPoseKey; mirror: boolean }\n\nconst trackOf = (clip: Pick<FirstPersonClip, 'keys'>, side: 'R' | 'L' | 'F'): Track[] => {\n const out: Track[] = []\n for (const key of clip.keys) {\n if (side === 'L') {\n if (key.L === 'mirror') {\n if (key.R) out.push({ t: key.t, key: key.R, mirror: true })\n } else if (key.L) out.push({ t: key.t, key: key.L, mirror: false })\n } else {\n const entry = key[side]\n if (entry) out.push({ t: key.t, key: entry, mirror: false })\n }\n }\n return out.sort((a, b) => a.t - b.t)\n}\n\nconst sampleTrack = (track: Track[], time: number): FirstPersonSampleChannel | undefined => {\n if (track.length === 0) return undefined\n const first = track[0]!\n const last = track[track.length - 1]!\n const of = (entry: Track): FirstPersonSampleChannel => ({ p: [...entry.key.p], r: [...entry.key.r], grip: entry.key.grip, w: entry.key.w ?? 1, mirror: entry.mirror })\n if (time <= first.t) return of(first)\n if (time >= last.t) return of(last)\n let index = 0\n while (index < track.length - 2 && time > track[index + 1]!.t) index++\n const a = track[index]!\n const b = track[index + 1]!\n const k = ease(Math.min(1, Math.max(0, (time - a.t) / (b.t - a.t))))\n const ga = a.key.grip\n const gb = b.key.grip\n return {\n p: mixTriple(a.key.p, b.key.p, k),\n r: mixTriple(a.key.r, b.key.r, k),\n grip: ga === undefined ? gb : gb === undefined ? ga : mix(ga, gb, k),\n w: mix(a.key.w ?? 1, b.key.w ?? 1, k),\n mirror: a.mirror,\n }\n}\n\n/** Where each driven channel is at `time`: between two keys of a channel the numbers are blended with the smoothstep of `samplePoseClip`; before its first key and after its last it holds them. */\nexport const sampleFirstPersonClip = (clip: Pick<FirstPersonClip, 'keys'>, time: number): FirstPersonSample => {\n const out: FirstPersonSample = {}\n for (const side of ['R', 'L', 'F'] as const) {\n const sample = sampleTrack(trackOf(clip, side), time)\n if (sample) out[side] = sample\n }\n return out\n}\n"],"mappings":"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","names":["isArm","limb","below","distance","MISSING_BITS","MISSING_BITS","blast","hitHead","hitLimb","distance","severity","blast","shoulderX"]}
|