@adatechnology/game-player 0.2.4 → 0.3.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 CHANGED
@@ -55,3 +55,7 @@ player.knock(1.5)
55
55
  `createPlayerTestModule()` (`player_area`, only the generic contracts) makes the room's camera the player body and puts the vitals on the bench;
56
56
  `examples/player-test-area` loads it into the shared test room (`PlayerArea.loadInto(room)`, `sala-jogador.html`), and `examples/interactables-test-area`
57
57
  carries it too.
58
+
59
+ ## Pushing furniture
60
+
61
+ `createFurniturePush(rules?)` is the logic of pushing a heavy thing on foot: `begin({ massKg, material })`, then `update(dt, { walk, isFree })` every frame answers the step and says the `phase` (`grip` while the hold timer fills, `push`, `strain`), the `progress` of the timer and the `block` (`too_heavy`, `obstacle`). The host answers `isFree` by sweeping the volume of the piece and draws the rest. `gripSecondsFor`, `pushSpeedFor` and `canPush` give the numbers; the force of the legs, the friction by material, the times and the speeds are all in `FurniturePushRules` (`FURNITURE_PUSH_DEFAULTS`).
package/dist/index.d.ts CHANGED
@@ -393,6 +393,74 @@ declare function createPlayer(options?: PlayerOptions): Player;
393
393
  /** Deterministic mulberry32 generator; returns floats in [0, 1). */
394
394
  declare function createRng(seed: number): () => number;
395
395
 
396
+ /**
397
+ * Pushing furniture on foot: hold the interaction button against a piece, a timer that grows with its mass fills, and the player then walks with it.
398
+ * Engine-agnostic: the host says where the player wants to go and answers whether the volume of the piece can go there; this says how fast, and when it locks.
399
+ */
400
+ type FurniturePushPhase = 'idle' | 'grip' | 'push' | 'strain';
401
+ type FurniturePushBlock = 'too_heavy' | 'obstacle' | null;
402
+ /** Every number of the push; a game overrides what it wants (`createFurniturePush(rules)`). */
403
+ interface FurniturePushRules {
404
+ /** The most the player's legs put on the floor, newtons: with the friction it says the heaviest thing that moves. */
405
+ readonly forceN: number;
406
+ readonly gravity: number;
407
+ /** Static friction of a base on a floor, by the material of the piece. */
408
+ readonly frictionByMaterial: Readonly<Record<string, number>>;
409
+ readonly defaultFriction: number;
410
+ /** The hold before the push: `base + perKg * mass`, at most `max` seconds. */
411
+ readonly gripSeconds: {
412
+ readonly base: number;
413
+ readonly perKg: number;
414
+ readonly max: number;
415
+ };
416
+ /** Metres per second: `max` with nothing on the hands, `min` at the limit of the force. */
417
+ readonly speed: {
418
+ readonly max: number;
419
+ readonly min: number;
420
+ };
421
+ /** A press shorter than this is not a push (the host keeps it for a tap, such as grabbing). */
422
+ readonly tapSeconds: number;
423
+ /** How long the effort stays after the last step that was refused, so that it does not flicker. */
424
+ readonly strainHoldSeconds: number;
425
+ }
426
+ declare const FURNITURE_PUSH_DEFAULTS: FurniturePushRules;
427
+ type FurniturePushTarget = {
428
+ readonly massKg: number;
429
+ readonly material?: string;
430
+ };
431
+ declare const gripSecondsFor: (massKg: number, rules?: FurniturePushRules) => number;
432
+ /** Whether the legs overcome the friction of the piece on the floor. */
433
+ declare const canPush: (target: FurniturePushTarget, rules?: FurniturePushRules) => boolean;
434
+ /** Metres per second with the piece on the hands: slower the closer it is to the limit of the force, 0 past it. */
435
+ declare const pushSpeedFor: (target: FurniturePushTarget, rules?: FurniturePushRules) => number;
436
+ type FurniturePushInput = {
437
+ /** Where the player wants to go on the floor: a unit vector, or `[0, 0]` standing. */
438
+ readonly walk: readonly [number, number];
439
+ /** Whether the volume of the piece (and the player behind it) can move by this offset. */
440
+ readonly isFree: (dx: number, dz: number) => boolean;
441
+ };
442
+ type FurniturePushStep = {
443
+ readonly dx: number;
444
+ readonly dz: number;
445
+ /** The grip closed on this update. */
446
+ readonly engaged: boolean;
447
+ /** A step was refused now and the one before was not: the moment the piece hits something. */
448
+ readonly hitObstacle: boolean;
449
+ };
450
+ interface FurniturePush {
451
+ readonly phase: FurniturePushPhase;
452
+ /** How far the hold timer is, 0 to 1. */
453
+ readonly progress: number;
454
+ readonly block: FurniturePushBlock;
455
+ readonly heldSeconds: number;
456
+ /** Whether the hold is still short enough to be a tap. */
457
+ readonly isTap: boolean;
458
+ begin(target: FurniturePushTarget): void;
459
+ release(): void;
460
+ update(dt: number, input: FurniturePushInput): FurniturePushStep;
461
+ }
462
+ declare function createFurniturePush(overrides?: Partial<FurniturePushRules>): FurniturePush;
463
+
396
464
  type PlayerText = Readonly<Record<PlayerMessageId | KnownDeathCause, string>>;
397
465
  declare const PLAYER_TEXT: Readonly<Record<'en' | 'pt-BR', PlayerText>>;
398
466
  /** The text of a message or death cause id in a locale (`pt-BR` or `en`, the language part is enough); unknown ids come back as they are. */
@@ -416,4 +484,4 @@ type PlayerTestModule = TestableModule<PlayerScenarioLike> & {
416
484
  */
417
485
  declare function createPlayerTestModule(options?: PlayerTestModuleOptions): PlayerTestModule;
418
486
 
419
- export { type AttributeId, type Attributes, type DeathCause, type Derived, type DerivedFormulas, type DerivedId, type InfectionRule, type KnownDeathCause, type LinearFormula, type MeleeItem, PLAYER_DEFAULTS, PLAYER_TEXT, type Player, type PlayerAction, type PlayerCrowd, type PlayerEvent, type PlayerEventMap, type PlayerEventName, type PlayerInput, type PlayerMessageId, type PlayerNumbers, type PlayerOptions, type PlayerSave, type PlayerSoundId, type PlayerState, type PlayerTestModule, type PlayerTestModuleOptions, type PlayerText, type PlayerWorld, type WoundRule, type WoundTable, createPlayer, createPlayerTestModule, createRng, deriveVitals, drawWound, playerTextOf };
487
+ export { type AttributeId, type Attributes, type DeathCause, type Derived, type DerivedFormulas, type DerivedId, FURNITURE_PUSH_DEFAULTS, type FurniturePush, type FurniturePushBlock, type FurniturePushInput, type FurniturePushPhase, type FurniturePushRules, type FurniturePushStep, type FurniturePushTarget, type InfectionRule, type KnownDeathCause, type LinearFormula, type MeleeItem, PLAYER_DEFAULTS, PLAYER_TEXT, type Player, type PlayerAction, type PlayerCrowd, type PlayerEvent, type PlayerEventMap, type PlayerEventName, type PlayerInput, type PlayerMessageId, type PlayerNumbers, type PlayerOptions, type PlayerSave, type PlayerSoundId, type PlayerState, type PlayerTestModule, type PlayerTestModuleOptions, type PlayerText, type PlayerWorld, type WoundRule, type WoundTable, canPush, createFurniturePush, createPlayer, createPlayerTestModule, createRng, deriveVitals, drawWound, gripSecondsFor, playerTextOf, pushSpeedFor };
@@ -21,14 +21,19 @@ var GamePlayer = (() => {
21
21
  // src/index.ts
22
22
  var index_exports = {};
23
23
  __export(index_exports, {
24
+ FURNITURE_PUSH_DEFAULTS: () => FURNITURE_PUSH_DEFAULTS,
24
25
  PLAYER_DEFAULTS: () => PLAYER_DEFAULTS,
25
26
  PLAYER_TEXT: () => PLAYER_TEXT,
27
+ canPush: () => canPush,
28
+ createFurniturePush: () => createFurniturePush,
26
29
  createPlayer: () => createPlayer,
27
30
  createPlayerTestModule: () => createPlayerTestModule,
28
31
  createRng: () => createRng,
29
32
  deriveVitals: () => deriveVitals,
30
33
  drawWound: () => drawWound,
31
- playerTextOf: () => playerTextOf
34
+ gripSecondsFor: () => gripSecondsFor,
35
+ playerTextOf: () => playerTextOf,
36
+ pushSpeedFor: () => pushSpeedFor
32
37
  });
33
38
 
34
39
  // src/data/defaults.json
@@ -635,6 +640,111 @@ var GamePlayer = (() => {
635
640
  };
636
641
  }
637
642
 
643
+ // src/furniture-push.ts
644
+ var FURNITURE_PUSH_DEFAULTS = {
645
+ forceN: 500,
646
+ gravity: 9.81,
647
+ frictionByMaterial: { wood_soft: 0.4, wood_hard: 0.4, mdf: 0.4, plywood: 0.4, steel: 0.35, aluminium: 0.35, cast_iron: 0.4, copper: 0.35, plastic: 0.35, rubber: 0.8, fabric: 0.45, foam: 0.5, ceramic: 0.5, glass: 0.3, tempered_glass: 0.3, brick: 0.6, concrete: 0.65 },
648
+ defaultFriction: 0.45,
649
+ gripSeconds: { base: 0.4, perKg: 0.015, max: 2.5 },
650
+ speed: { max: 1.8, min: 0.35 },
651
+ tapSeconds: 0.2,
652
+ strainHoldSeconds: 0.25
653
+ };
654
+ var frictionOf = (target, rules) => (target.material !== void 0 ? rules.frictionByMaterial[target.material] : void 0) ?? rules.defaultFriction;
655
+ var loadShare = (target, rules) => frictionOf(target, rules) * target.massKg * rules.gravity / rules.forceN;
656
+ var gripSecondsFor = (massKg, rules = FURNITURE_PUSH_DEFAULTS) => Math.min(rules.gripSeconds.max, rules.gripSeconds.base + rules.gripSeconds.perKg * Math.max(0, massKg));
657
+ var canPush = (target, rules = FURNITURE_PUSH_DEFAULTS) => loadShare(target, rules) <= 1;
658
+ var pushSpeedFor = (target, rules = FURNITURE_PUSH_DEFAULTS) => {
659
+ const share = loadShare(target, rules);
660
+ return share > 1 ? 0 : rules.speed.max + (rules.speed.min - rules.speed.max) * share;
661
+ };
662
+ var STILL = { dx: 0, dz: 0, engaged: false, hitObstacle: false };
663
+ function createFurniturePush(overrides = {}) {
664
+ const rules = { ...FURNITURE_PUSH_DEFAULTS, ...overrides };
665
+ let phase = "idle";
666
+ let target = { massKg: 0 };
667
+ let held = 0;
668
+ let gripSeconds = 1;
669
+ let speed = 0;
670
+ let block = null;
671
+ let refused = 0;
672
+ let wasRefused = false;
673
+ const walkWith = (dt, input) => {
674
+ refused = Math.max(0, refused - dt);
675
+ if (block === "too_heavy") return STILL;
676
+ const [x, z] = input.walk;
677
+ if (x === 0 && z === 0 || dt <= 0) {
678
+ if (refused === 0) {
679
+ phase = "push";
680
+ block = null;
681
+ wasRefused = false;
682
+ }
683
+ return STILL;
684
+ }
685
+ const dx = x * speed * dt;
686
+ const dz = z * speed * dt;
687
+ if (input.isFree(dx, dz)) {
688
+ if (refused === 0) {
689
+ phase = "push";
690
+ block = null;
691
+ }
692
+ wasRefused = false;
693
+ return { dx, dz, engaged: false, hitObstacle: false };
694
+ }
695
+ const hitObstacle = !wasRefused;
696
+ wasRefused = true;
697
+ refused = rules.strainHoldSeconds;
698
+ phase = "strain";
699
+ block = "obstacle";
700
+ return { dx: 0, dz: 0, engaged: false, hitObstacle };
701
+ };
702
+ return {
703
+ get phase() {
704
+ return phase;
705
+ },
706
+ get progress() {
707
+ return phase === "idle" ? 0 : Math.min(1, held / gripSeconds);
708
+ },
709
+ get block() {
710
+ return block;
711
+ },
712
+ get heldSeconds() {
713
+ return held;
714
+ },
715
+ get isTap() {
716
+ return phase === "grip" && held < rules.tapSeconds;
717
+ },
718
+ begin(next) {
719
+ target = next;
720
+ phase = "grip";
721
+ held = 0;
722
+ block = null;
723
+ refused = 0;
724
+ wasRefused = false;
725
+ gripSeconds = gripSecondsFor(next.massKg, rules);
726
+ speed = pushSpeedFor(next, rules);
727
+ },
728
+ release() {
729
+ phase = "idle";
730
+ held = 0;
731
+ block = null;
732
+ },
733
+ update(dt, input) {
734
+ if (phase === "idle") return STILL;
735
+ held += dt;
736
+ if (phase !== "grip") return walkWith(dt, input);
737
+ if (held < gripSeconds) return STILL;
738
+ if (canPush(target, rules)) phase = "push";
739
+ else {
740
+ phase = "strain";
741
+ block = "too_heavy";
742
+ }
743
+ return { ...STILL, engaged: true };
744
+ }
745
+ };
746
+ }
747
+
638
748
  // src/locales/index.ts
639
749
  var PT_BR = {
640
750
  grabbed: "AGARRADO! Aperte E v\xE1rias vezes para empurrar ou F para a faca",
@@ -1023,6 +1133,7 @@ var GamePlayer = (() => {
1023
1133
  const module = {
1024
1134
  id: "player_area",
1025
1135
  name: text.name,
1136
+ ground: { surface: "dirt" },
1026
1137
  group: text.group,
1027
1138
  get player() {
1028
1139
  return player;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/data/defaults.json","../src/rng.ts","../src/player.ts","../src/locales/index.ts","../src/bench/locale.ts","../src/bench/module.ts"],"sourcesContent":["export { PLAYER_DEFAULTS, createPlayer, deriveVitals, drawWound } from './player'\nexport type { Player, PlayerOptions } from './player'\nexport { createRng } from './rng'\nexport { PLAYER_TEXT, playerTextOf } from './locales'\nexport type { PlayerText } from './locales'\nexport { createPlayerTestModule } from './bench/module'\nexport type { PlayerTestModule, PlayerTestModuleOptions } from './bench/module'\nexport type * from './types'\n","{\n \"sources\": {\n \"game\": \"specs/001-migracao-entregas-dos-times/artefatos/2UG1Mhe9LqJkQKKVsJkTWR/jogo.js\",\n \"attributes\": \"G 62004 FICHA (Personagens 3.2: every attribute 5, no traits)\",\n \"derived\": \"G 62005-62012 DERIV\",\n \"wounds\": \"G 62016 FERIDA (Personagens 3.7): share of each wound kind, and its infection chance (used only when an infection rule is on)\",\n \"infection\": \"G 62015 INFEC (the slice's accelerated clock: fever 30 s, delirium 70 s, death 120 s, reanimation 8 s after); G 68509 fever noise\",\n \"numbers\": \"G 68427-68640 player, playerUpdate, frontZombies, shove, knife; G 68678-68681 the aim spread modifiers; G 65507 walkCad\"\n },\n \"attributes\": { \"strength\": 5, \"vigor\": 5, \"agility\": 5, \"perception\": 5, \"intellect\": 5, \"presence\": 5 },\n \"derived\": {\n \"maxHealth\": { \"base\": 70, \"terms\": [[\"vigor\", 6]] },\n \"maxStamina\": { \"base\": 40, \"terms\": [[\"vigor\", 6], [\"agility\", 4]] },\n \"runSpeed\": { \"base\": 5.2, \"terms\": [[\"agility\", 0.12]] },\n \"walkSpeed\": { \"base\": 1.6, \"terms\": [] },\n \"footstepNoise\": { \"base\": 100, \"terms\": [[\"agility\", -4]], \"divide\": 100 },\n \"composure\": { \"base\": 20, \"terms\": [[\"vigor\", 3], [\"presence\", 4]] }\n },\n \"wounds\": {\n \"scratch\": { \"share\": 0.6, \"infectionChance\": 0.06, \"bleeds\": false },\n \"laceration\": { \"share\": 0.3, \"infectionChance\": 0.22, \"bleeds\": true },\n \"bite\": { \"share\": 0.1, \"infectionChance\": 1, \"bleeds\": true }\n },\n \"infection\": {\n \"feverSeconds\": 30,\n \"deliriumSeconds\": 70,\n \"deathSeconds\": 120,\n \"reanimateSeconds\": 8,\n \"feverNoiseEvery\": 2,\n \"feverNoiseChance\": 0.5,\n \"feverNoiseRadius\": 10,\n \"feverNoiseVolume\": 2,\n \"feverSpeed\": 0.85,\n \"feverSpread\": 1.5\n },\n \"numbers\": {\n \"hurtFlash\": 0.4,\n \"hurtVolume\": 0.8,\n \"biteDamage\": 25,\n \"biteFlash\": 0.8,\n \"biteVolume\": 1.2,\n \"burnPerSecond\": 3,\n \"bleedPerSecond\": 0.15,\n \"grabSeconds\": 3,\n \"grabVolume\": 1,\n \"grabFollow\": 12,\n \"grabOffset\": 0.55,\n \"grabPushCost\": 6,\n \"grabPushMinStamina\": 5,\n \"grabPushVolume\": 1.5,\n \"grabPushes\": 6,\n \"grabPushStun\": 1.2,\n \"grabPushSpeed\": 3,\n \"grabKnifeChance\": 0.7,\n \"grabKnifeRegion\": 0,\n \"grabKnifeDamage\": 22,\n \"grabKnifeDistance\": 0.5,\n \"grabKnifeCut\": 0.7,\n \"drownDamage\": 30,\n \"drownFlash\": 0.8,\n \"noJawDamage\": 8,\n \"grabAttackCooldown\": 2,\n \"vaultSeconds\": 0.7,\n \"vaultCost\": 15,\n \"vaultHeight\": 1.9,\n \"vaultScanFrom\": 0.3,\n \"vaultScanTo\": 1.0,\n \"vaultScanStep\": 0.1,\n \"vaultLandFrom\": 0.4,\n \"vaultLandTo\": 1.4,\n \"vaultClearance\": 0.3,\n \"vaultCheckHeight\": 0.4,\n \"vaultNoise\": 6,\n \"vaultStartVolume\": 0.8,\n \"vaultLandVolume\": 1,\n \"crouchSpeed\": 1.0,\n \"walkFactor\": 1.35,\n \"aimSpeedCap\": 1.4,\n \"waterSpeed\": 0.55,\n \"runMinStamina\": 1,\n \"runDrain\": 12,\n \"regenMoving\": 4,\n \"regenStill\": 8,\n \"acceleration\": 10,\n \"radius\": 0.3,\n \"blockHeight\": 0.4,\n \"pushApartRadius\": 0.55,\n \"pushApartHeight\": 1.2,\n \"hipFollow\": 10,\n \"hipMinSpeed\": 0.3,\n \"hipLimit\": 0.9,\n \"backwardsBelow\": -0.1,\n \"cadenceBase\": 0.5,\n \"cadencePerSpeed\": 0.3,\n \"cadenceMinSpeed\": 0.05,\n \"turnFollow\": 12,\n \"stepEvery\": 0.75,\n \"stepMinSpeed\": 0.3,\n \"stepNoiseRun\": 8,\n \"stepNoiseWalk\": 3,\n \"stepNoiseCrouch\": 1,\n \"stepNoiseWater\": 2,\n \"stepVolumeRun\": 0.6,\n \"stepVolumeWalk\": 0.3,\n \"shoveCost\": 10,\n \"shoveVolume\": 1.2,\n \"shoveRange\": 1.6,\n \"shoveCone\": 0.3,\n \"shoveStun\": 0.9,\n \"shoveSpeed\": 2.5,\n \"meleeMinStamina\": 5,\n \"meleeCostLight\": 5,\n \"meleeCostHeavy\": 12,\n \"meleeHeavyKg\": 1.5,\n \"meleeVolume\": 0.6,\n \"meleeRangeBase\": 0.9,\n \"meleeCone\": 0.5,\n \"meleeHeadChance\": 0.35,\n \"meleeArmChance\": 0.5,\n \"meleeStrengthPerPoint\": 0.06,\n \"meleeStrengthBase\": 5,\n \"meleeCritToCut\": 60,\n \"panicGain\": 1.2,\n \"panicDecay\": 3,\n \"panicMax\": 100,\n \"panicSpreadAt\": 0.6,\n \"panicSpread\": 1.4,\n \"moveSpread\": 0.4\n },\n \"fist\": { \"damage\": 8, \"crit\": 0, \"reach\": 0.5, \"noise\": 1 }\n}\n","const FNV_OFFSET = 0x811c9dc5\nconst FNV_PRIME = 0x01000193\nconst MIX = 0x9e3779b1\n\n/** Deterministic mulberry32 generator; returns floats in [0, 1). */\nexport function 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/** A seed for the stream called `name`: the same seed gives each name its own sequence, so lightning never shifts the schedule. */\nexport function streamSeed(seed: number, name: string): number {\n let hash = FNV_OFFSET\n for (let index = 0; index < name.length; index++) hash = Math.imul(hash ^ name.charCodeAt(index), FNV_PRIME) >>> 0\n return Math.imul((seed >>> 0) ^ hash, MIX) >>> 0\n}\n\nexport function createStream(seed: number, name: string): () => number {\n return createRng(streamSeed(seed, name))\n}\n\nexport function drawBetween(rng: () => number, range: readonly [min: number, max: number]): number {\n return range[0] + rng() * (range[1] - range[0])\n}\n","import defaults from './data/defaults.json'\nimport { createRng } from './rng'\nimport type {\n Attributes,\n DeathCause,\n Derived,\n DerivedFormulas,\n DerivedId,\n InfectionRule,\n LinearFormula,\n MeleeItem,\n PlayerAction,\n PlayerCrowd,\n PlayerEventMap,\n PlayerEventName,\n PlayerInput,\n PlayerMessageId,\n PlayerNumbers,\n PlayerSave,\n PlayerSoundId,\n PlayerState,\n PlayerWorld,\n WoundTable,\n} from './types'\n\nexport const PLAYER_DEFAULTS = defaults as unknown as {\n readonly sources: Readonly<Record<string, string>>\n readonly attributes: Attributes\n readonly derived: DerivedFormulas\n readonly wounds: WoundTable\n readonly infection: InfectionRule\n readonly numbers: PlayerNumbers\n readonly fist: MeleeItem\n}\n\nexport type PlayerOptions = {\n /** The random stream (the game passes its single stream). Default `createRng(seed)`. */\n readonly random?: () => number\n readonly seed?: number\n /** The sheet: every attribute 5 by default. */\n readonly attributes?: Partial<Attributes>\n readonly derived?: Partial<DerivedFormulas>\n readonly wounds?: WoundTable\n /** An individual infection (`true` uses the defaults; an object patches them). Off by default: the normal world comes first. */\n readonly infection?: boolean | Partial<InfectionRule>\n readonly numbers?: Partial<PlayerNumbers>\n readonly fist?: MeleeItem\n readonly position?: { readonly x?: number; readonly z?: number; readonly yaw?: number }\n readonly world?: PlayerWorld\n}\n\nexport type Player = {\n readonly state: PlayerState\n readonly attributes: Attributes\n readonly derived: Derived\n readonly numbers: PlayerNumbers\n readonly infection: InfectionRule | null\n update(dt: number, input?: PlayerInput, world?: PlayerWorld): void\n /** A hit that opens a wound (drawn from the wound table) and may infect. `by` is the agent that hit, if any. */\n hurt(amount: number, by?: number): void\n /** A bite: damage, bleeding, a bite wound and (with an infection rule) the infection. */\n bite(by?: number): void\n grab(by: number, noJaw?: boolean, drown?: boolean): void\n release(): void\n knock(seconds: number): void\n infect(source: string): void\n /** Kills the player with a cause (the host's deaths: a fall, a fire). */\n die(cause: DeathCause): void\n /** Infection stage: `none`, `malaise`, `fever`, `delirium`. */\n stage(): 'none' | 'malaise' | 'fever' | 'delirium'\n /** Seconds the infection has left, or null. */\n timeLeft(): number | null\n /** What the player's state does to aim spread (panic, fever, moving); the weapon multiplies its own spread by it. */\n spreadFactor(): number\n /** The agents in front (nearest first) within `range` m and a cone of `cosMin`, as `[distance, index]`. */\n front(range: number, cosMin: number, yaw: number, crowd?: PlayerCrowd): [number, number][]\n on<K extends PlayerEventName>(event: K, listener: (event: PlayerEventMap[K]) => void): () => void\n save(): PlayerSave\n load(save: PlayerSave): void\n /** The world `update` uses when it is given none. */\n setWorld(world: PlayerWorld): void\n}\n\nconst TAU_APPROX = 6.2832\n\nconst evaluate = (formula: LinearFormula, attributes: Attributes): number => {\n let value = formula.base\n for (const [attribute, coefficient] of formula.terms) value += coefficient * attributes[attribute]\n return formula.divide === undefined ? value : value / formula.divide\n}\n\n/** The derived values of a sheet (the game's `DERIV`). */\nexport const deriveVitals = (attributes: Attributes, formulas: DerivedFormulas = PLAYER_DEFAULTS.derived): Derived => {\n const out = {} as Record<DerivedId, number>\n for (const id of Object.keys(formulas) as DerivedId[]) out[id] = evaluate(formulas[id], attributes)\n return out\n}\n\n/** Which wound a hit opens: one draw, the kinds in the listed order, the last one takes the rest (the game's `FERIDA` draw). */\nexport const drawWound = (wounds: WoundTable, random: () => number): string => {\n const kinds = Object.keys(wounds)\n const draw = random()\n let acc = 0\n for (let k = 0; k < kinds.length - 1; k++) {\n acc += wounds[kinds[k]!]!.share\n if (draw < acc) return kinds[k]!\n }\n return kinds[kinds.length - 1]!\n}\n\nconst clamp = (v: number, a: number, b: number): number => (v < a ? a : v > b ? b : v)\nconst lerp = (a: number, b: number, t: number): number => a + (b - a) * t\n\nconst freshState = (derived: Derived, position: PlayerOptions['position']): PlayerState => ({\n x: position?.x ?? 0,\n z: position?.z ?? 0,\n y: 0,\n vx: 0,\n vz: 0,\n yaw: position?.yaw ?? 0,\n floor: 0,\n alive: true,\n turned: false,\n health: derived.maxHealth,\n stamina: derived.maxStamina,\n crouch: false,\n running: false,\n stepTimer: 0,\n phase: 0,\n hip: 0,\n grabbedBy: -1,\n grabTimer: 0,\n grabPushes: 0,\n grabNoJaw: false,\n grabDrown: false,\n infected: false,\n infectionTime: 0,\n infectionSource: '',\n wounds: [],\n bleeding: 0,\n blind: 0,\n screamBoost: 0,\n panic: 0,\n hurtFlash: 0,\n deathTime: 0,\n cause: '',\n downTimer: 0,\n burnTimer: 0,\n scentTimer: 0,\n vaultTimer: 0,\n vault: null,\n})\n\n/**\n * The player body: a literal port of the team game's `player` and `playerUpdate` (G 68427-68640) with the world, the crowd and the input as\n * arguments instead of globals. The draws on `random` happen in the game's order (wound kind, infection, the fever cough, the knife when grabbed,\n * the melee region), so a game that passes its own stream keeps its sequence.\n */\nexport function createPlayer(options: PlayerOptions = {}): Player {\n const random = options.random ?? createRng(options.seed ?? 1)\n const attributes: Attributes = { ...PLAYER_DEFAULTS.attributes, ...options.attributes }\n const formulas: DerivedFormulas = { ...PLAYER_DEFAULTS.derived, ...options.derived }\n const derived = deriveVitals(attributes, formulas)\n const numbers: PlayerNumbers = { ...PLAYER_DEFAULTS.numbers, ...options.numbers }\n const wounds = options.wounds ?? PLAYER_DEFAULTS.wounds\n const infection: InfectionRule | null =\n options.infection === undefined || options.infection === false ? null : options.infection === true ? PLAYER_DEFAULTS.infection : { ...PLAYER_DEFAULTS.infection, ...options.infection }\n const fist = options.fist ?? PLAYER_DEFAULTS.fist\n const listeners = new Map<PlayerEventName, Set<(event: never) => void>>()\n let P = freshState(derived, options.position)\n let defaultWorld: PlayerWorld = options.world ?? {}\n let world: PlayerWorld = defaultWorld\n\n const emit = <K extends PlayerEventName>(event: K, payload: PlayerEventMap[K]): void => {\n const set = listeners.get(event)\n if (set) for (const listener of set) (listener as (event: PlayerEventMap[K]) => void)(payload)\n }\n const sound = (id: PlayerSoundId, volume: number): void => emit('sound', { sound: id, volume, position: [P.x, P.y, P.z] })\n const noise = (x: number, z: number, radius: number): void => emit('noise', { x, z, radius })\n const message = (id: PlayerMessageId | DeathCause, seconds: number): void => emit('message', { id, seconds })\n const inWater = (x: number, z: number): boolean => world.inWater?.(x, z) ?? false\n const solidAt = (x: number, z: number, y: number): boolean => world.solidAt?.(x, z, y) ?? false\n const cellKind = (x: number, z: number): number => world.cellKind?.(x, z) ?? 0\n const blocked = (x: number, z: number): boolean => (world.blocked ? world.blocked(x, z) : solidAt(x, z, numbers.blockHeight))\n const chanceOf = (kind: string): number => infection?.chances?.[kind] ?? wounds[kind]?.infectionChance ?? 0\n\n const die = (cause: DeathCause): void => {\n if (!P.alive) return\n P.alive = false\n P.cause = cause\n P.deathTime = 0\n P.grabbedBy = -1\n message(cause, 6)\n emit('died', { cause })\n }\n const infect = (source: string): void => {\n if (P.infected || !infection) return\n P.infected = true\n P.infectionTime = 0\n P.infectionSource = source\n emit('infected', { source })\n }\n const release = (how: PlayerEventMap['released']['how'] = 'free'): void => {\n const by = P.grabbedBy\n P.grabbedBy = -1\n if (by >= 0) emit('released', { by, how })\n }\n const hurt = (amount: number): void => {\n if (!P.alive) return\n P.health -= amount\n P.hurtFlash = numbers.hurtFlash\n sound('flesh', numbers.hurtVolume)\n const kind = drawWound(wounds, random)\n P.wounds.push(kind)\n if (wounds[kind]?.bleeds) P.bleeding = 1\n emit('hurt', { amount, wound: kind })\n if (infection && !P.infected && random() < chanceOf(kind)) infect(kind)\n if (P.health <= 0) die(P.infected ? 'infected' : 'killed')\n }\n const bite = (): void => {\n P.health -= numbers.biteDamage\n P.hurtFlash = numbers.biteFlash\n P.bleeding = 1\n P.wounds.push('bite')\n sound('flesh', numbers.biteVolume)\n emit('hurt', { amount: numbers.biteDamage, wound: 'bite' })\n infect('bite')\n message('bitten', 5)\n if (P.health <= 0) die('bitten_to_death')\n }\n const grab = (by: number, noJaw = false, drown = false): void => {\n P.grabbedBy = by\n P.grabTimer = numbers.grabSeconds\n P.grabPushes = 0\n P.grabNoJaw = noJaw\n P.grabDrown = drown\n message(drown ? 'grabbed_drown' : 'grabbed', 3)\n sound('flesh', numbers.grabVolume)\n emit('grabbed', { by, noJaw, drown })\n }\n\n const front = (range: number, cosMin: number, yaw: number, crowd: PlayerCrowd | undefined = world.crowd): [number, number][] => {\n const out: [number, number][] = []\n if (!crowd) return out\n const fx = -Math.sin(yaw)\n const fz = -Math.cos(yaw)\n const n = crowd.count()\n for (let i = 0; i < n; i++) {\n if (!crowd.active(i) || crowd.floor(i) !== P.floor) continue\n const ex = crowd.x(i) - P.x\n const ez = crowd.z(i) - P.z\n const d = Math.hypot(ex, ez)\n if (d < range && (ex * fx + ez * fz) / (d || 1) > cosMin) out.push([d, i])\n }\n return out.sort((a, b) => a[0] - b[0])\n }\n\n const shove = (yaw: number): void => {\n sound('step', numbers.shoveVolume)\n const crowd = world.crowd\n const targets: number[] = []\n for (const [d, i] of front(numbers.shoveRange, numbers.shoveCone, yaw)) {\n crowd!.stun(i, numbers.shoveStun, ((crowd!.x(i) - P.x) / d) * numbers.shoveSpeed, ((crowd!.z(i) - P.z) / d) * numbers.shoveSpeed)\n targets.push(i)\n }\n emit('shove', { targets })\n }\n\n const melee = (item: MeleeItem, yaw: number): void => {\n const t = front(numbers.meleeRangeBase + (item.reach ?? 0), numbers.meleeCone, yaw)[0]\n sound('flesh', numbers.meleeVolume)\n noise(P.x, P.z, item.noise || 1)\n if (!t) return\n const crowd = world.crowd!\n const i = t[1]\n // a blow to the head is x3 in melee; on the ground or crawling it is an execution\n const region = crowd.down(i) ? 0 : random() < numbers.meleeHeadChance ? 0 : random() < numbers.meleeArmChance ? 1 : 2 + Math.floor(random() * 2)\n const damage = item.damage * (1 + (attributes.strength - numbers.meleeStrengthBase) * numbers.meleeStrengthPerPoint)\n const cut = Math.min(1, (item.crit || 0) / numbers.meleeCritToCut)\n crowd.damage(i, { region, amount: damage, distance: t[0], cut })\n emit('melee', { target: i, region, damage, distance: t[0], cut })\n }\n\n const update = (dt: number, input: PlayerInput = {}, frameWorld?: PlayerWorld): void => {\n world = frameWorld ?? defaultWorld\n if (!P.alive) {\n P.deathTime += dt\n if (P.infected && infection && !P.turned && P.deathTime >= infection.reanimateSeconds) {\n P.turned = true\n emit('turned', { x: P.x, z: P.z, floor: P.floor })\n }\n return\n }\n const pressed: Partial<Record<PlayerAction, boolean>> = { ...input.pressed }\n const wasPressed = (action: PlayerAction): boolean => {\n const v = pressed[action] === true\n pressed[action] = false\n return v\n }\n const viewYaw = input.yaw ?? 0\n const crowd = world.crowd\n P.screamBoost = Math.max(0, P.screamBoost - dt)\n P.blind = Math.max(0, P.blind - dt)\n P.hurtFlash = Math.max(0, P.hurtFlash - dt)\n // infection on its own clock\n if (P.infected && infection) {\n const before = P.infectionTime\n P.infectionTime += dt\n if (before <= infection.feverSeconds && P.infectionTime > infection.feverSeconds) emit('stage', { stage: 'fever' })\n if (before <= infection.deliriumSeconds && P.infectionTime > infection.deliriumSeconds) emit('stage', { stage: 'delirium' })\n const every = 1 / infection.feverNoiseEvery\n if (P.infectionTime > infection.feverSeconds && Math.floor(P.infectionTime * every) !== Math.floor((P.infectionTime - dt) * every) && random() < infection.feverNoiseChance) {\n noise(P.x, P.z, infection.feverNoiseRadius)\n sound('step', infection.feverNoiseVolume)\n }\n if (P.infectionTime > infection.deathSeconds) {\n P.health = 0\n die('infection')\n return\n }\n }\n if (P.burnTimer > 0) {\n P.burnTimer -= dt\n P.health -= numbers.burnPerSecond * dt\n if (inWater(P.x, P.z)) P.burnTimer = 0\n }\n P.scentTimer = Math.max(0, P.scentTimer - dt)\n if (P.bleeding) {\n P.health -= dt * numbers.bleedPerSecond\n if (input.bandage && P.bleeding) {\n P.bleeding = 0\n message('bandaged', 2)\n }\n }\n if (P.health <= 0) {\n die(P.infected ? 'infected' : P.bleeding ? 'bled_out' : 'hunger_thirst')\n return\n }\n // grabbed: seconds to react\n if (P.grabbedBy >= 0) {\n const i = P.grabbedBy\n P.grabTimer -= dt\n if (crowd) {\n const k = 1 - Math.exp(-dt * numbers.grabFollow) // glued to the body without a jump\n crowd.hold(i, P.x - Math.sin(P.yaw) * numbers.grabOffset, P.z - Math.cos(P.yaw) * numbers.grabOffset, k, P.x, P.z)\n }\n if (wasPressed('push') && P.stamina > numbers.grabPushMinStamina) {\n P.grabPushes++\n P.stamina -= numbers.grabPushCost\n sound('step', numbers.grabPushVolume)\n }\n if (wasPressed('knife')) {\n if (random() < numbers.grabKnifeChance) {\n crowd?.damage(i, { region: numbers.grabKnifeRegion, amount: numbers.grabKnifeDamage, distance: numbers.grabKnifeDistance, cut: numbers.grabKnifeCut })\n message('knife_head', 1.5)\n release('knife')\n return\n } else message('knife_miss', 1)\n }\n if (P.grabPushes >= numbers.grabPushes) {\n crowd?.stun(i, numbers.grabPushStun, -Math.sin(viewYaw) * numbers.grabPushSpeed, -Math.cos(viewYaw) * numbers.grabPushSpeed)\n release('push')\n message('pushed_off', 1.2)\n return\n }\n if (P.grabTimer <= 0) {\n if (P.grabDrown) {\n P.health -= numbers.drownDamage\n P.hurtFlash = numbers.drownFlash\n message('drowning', 2)\n if (P.health <= 0) {\n die('drowned')\n return\n }\n P.grabTimer = numbers.grabSeconds\n P.grabPushes = 0\n return\n }\n if (P.grabNoJaw) {\n hurt(numbers.noJawDamage)\n message('no_jaw', 2)\n } else bite()\n crowd?.chase(i, numbers.grabAttackCooldown)\n release(P.grabNoJaw ? 'scratch' : 'bite')\n }\n return\n }\n // knocked down\n if (P.downTimer > 0) {\n P.downTimer -= dt\n P.vx = P.vz = 0\n if (P.downTimer <= 0) message('stood_up', 0.8)\n return\n }\n if (world.busy?.(dt)) return\n // vaulting a low wall\n if (P.vaultTimer > 0 && P.vault) {\n P.vaultTimer -= dt\n const k = 1 - P.vaultTimer / numbers.vaultSeconds\n P.x = lerp(P.vault[0], P.vault[2], k)\n P.z = lerp(P.vault[1], P.vault[3], k)\n P.y = Math.sin(k * Math.PI) * numbers.vaultHeight\n if (P.vaultTimer <= 0) {\n P.y = 0\n noise(P.x, P.z, numbers.vaultNoise)\n sound('step', numbers.vaultLandVolume)\n }\n return\n }\n if (wasPressed('vault') && P.stamina > numbers.vaultCost && (world.canVault?.() ?? !P.floor)) {\n const fx0 = -Math.sin(viewYaw)\n const fz0 = -Math.cos(viewYaw)\n for (let a = numbers.vaultScanFrom; a <= numbers.vaultScanTo; a += numbers.vaultScanStep) {\n const c = cellKind(P.x + fx0 * a, P.z + fz0 * a)\n if (c === 2) {\n for (let e = a + numbers.vaultLandFrom; e <= a + numbers.vaultLandTo; e += numbers.vaultScanStep) {\n const ex = P.x + fx0 * e\n const ez = P.z + fz0 * e\n if (!solidAt(ex, ez, numbers.vaultCheckHeight) && !solidAt(ex + fx0 * numbers.vaultClearance, ez + fz0 * numbers.vaultClearance, numbers.vaultCheckHeight)) {\n P.vault = [P.x, P.z, ex, ez]\n P.vaultTimer = numbers.vaultSeconds\n P.stamina -= numbers.vaultCost\n sound('step', numbers.vaultStartVolume)\n emit('vault', { from: [P.x, P.z], to: [ex, ez] })\n return\n }\n }\n break\n }\n if (c > 0 && c !== 3) break\n }\n }\n // movement\n const f = input.forward ?? 0\n const s = input.right ?? 0\n if (wasPressed('crouch')) P.crouch = !P.crouch\n const want = f || s\n P.running = !!(input.run && want && P.stamina > numbers.runMinStamina && !input.aim && !P.crouch)\n const fever = P.infected && infection !== null && P.infectionTime > infection.feverSeconds\n let sp = P.running ? derived.runSpeed : P.crouch ? numbers.crouchSpeed : derived.walkSpeed * numbers.walkFactor\n if (fever) sp *= infection!.feverSpeed\n if (input.aim) sp = Math.min(sp, numbers.aimSpeedCap)\n const wet = inWater(P.x, P.z)\n if (wet) sp *= numbers.waterSpeed\n if (P.running) P.stamina = Math.max(0, P.stamina - numbers.runDrain * dt)\n else P.stamina = Math.min(derived.maxStamina, P.stamina + (want ? numbers.regenMoving : numbers.regenStill) * dt)\n const fx = -Math.sin(viewYaw)\n const fz = -Math.cos(viewYaw)\n const mx = fx * f - fz * s\n const mz = fz * f + fx * s\n const ml = Math.hypot(mx, mz) || 1\n const tvx = want ? (mx / ml) * sp : 0\n const tvz = want ? (mz / ml) * sp : 0\n P.vx = lerp(P.vx, tvx, Math.min(1, dt * numbers.acceleration))\n P.vz = lerp(P.vz, tvz, Math.min(1, dt * numbers.acceleration))\n const r = numbers.radius\n const nx = P.x + P.vx * dt\n const nz = P.z + P.vz * dt\n if (!blocked(nx + Math.sign(P.vx) * r, P.z)) P.x = nx\n if (!blocked(P.x, nz + Math.sign(P.vz) * r)) P.z = nz\n world.afterMove?.(P)\n // the player does not walk through the crowd: agents pressed against the body push it out\n if (crowd) {\n const n = crowd.count()\n const rr = numbers.pushApartRadius\n for (let i = 0; i < n; i++) {\n if (!crowd.active(i) || Math.abs(crowd.y(i) - P.y) > numbers.pushApartHeight) continue\n const ex = P.x - crowd.x(i)\n const ez = P.z - crowd.z(i)\n const e2 = ex * ex + ez * ez\n if (e2 < rr * rr && e2 > 1e-5) {\n const e = Math.sqrt(e2)\n const k = ((rr - e) / e) * 0.5\n if (!solidAt(P.x + ex * k, P.z + ez * k, numbers.blockHeight)) {\n P.x += ex * k\n P.z += ez * k\n }\n }\n }\n }\n const spd = Math.hypot(P.vx, P.vz)\n // the legs follow the move even with the torso on the aim; walking backwards flips the stride\n {\n const cy = Math.cos(P.yaw)\n const sy = Math.sin(P.yaw)\n const lx = P.vx * cy - P.vz * sy\n const lz = P.vx * sy + P.vz * cy\n const back = lz < numbers.backwardsBelow ? -1 : 1\n const hip = spd > numbers.hipMinSpeed ? clamp(Math.atan2(lx * back, lz * back), -numbers.hipLimit, numbers.hipLimit) : 0\n P.hip = P.hip + (hip - P.hip) * Math.min(1, dt * numbers.hipFollow)\n P.phase += dt * (spd < numbers.cadenceMinSpeed ? 0 : numbers.cadenceBase + numbers.cadencePerSpeed * spd) * back\n }\n // the body follows the view (fast, no snap); aiming or firing, at once\n {\n const target = viewYaw + Math.PI\n let dy = target - P.yaw\n dy -= Math.round(dy / TAU_APPROX) * TAU_APPROX\n P.yaw += input.aim || input.firing ? dy : dy * Math.min(1, dt * numbers.turnFollow)\n }\n // footsteps make noise: walk 3 m, run 8 m, crouched 1 m (x the sheet's footstep noise, x2 in water)\n P.stepTimer -= dt * spd\n if (P.stepTimer <= 0 && spd > numbers.stepMinSpeed) {\n P.stepTimer = numbers.stepEvery\n noise(P.x, P.z, (P.running ? numbers.stepNoiseRun : P.crouch ? numbers.stepNoiseCrouch : numbers.stepNoiseWalk) * derived.footstepNoise * (wet ? numbers.stepNoiseWater : 1))\n sound('step', P.running ? numbers.stepVolumeRun : numbers.stepVolumeWalk)\n emit('step', { x: P.x, z: P.z, yaw: P.yaw })\n }\n // shove and melee\n if (wasPressed('push') && P.stamina > numbers.shoveCost) {\n P.stamina -= numbers.shoveCost\n shove(viewYaw)\n }\n if (wasPressed('throw')) emit('throw', {})\n if (wasPressed('knife') && P.stamina > numbers.meleeMinStamina) {\n const item = input.melee ?? fist\n P.stamina -= (item.kg ?? 0) > numbers.meleeHeavyKg ? numbers.meleeCostHeavy : numbers.meleeCostLight\n melee(item, viewYaw)\n }\n // panic: chasing agents in sight nearby\n let near = 0\n if (crowd) {\n const n = crowd.count()\n for (let i = 0; i < n; i++) if (crowd.active(i) && crowd.chasing(i)) near += crowd.panicWeight?.(i) ?? 1\n }\n P.panic = clamp(P.panic + (near * numbers.panicGain - (near ? 0 : numbers.panicDecay)) * dt, 0, numbers.panicMax)\n }\n\n return {\n get state() {\n return P\n },\n attributes,\n derived,\n numbers,\n infection,\n update,\n hurt: (amount) => hurt(amount),\n bite: () => bite(),\n grab,\n release: () => release('free'),\n knock(seconds) {\n if (!P.alive) return\n P.downTimer = Math.max(P.downTimer, seconds)\n P.crouch = false\n },\n infect,\n die,\n stage() {\n if (!P.infected || !infection) return 'none'\n return P.infectionTime > infection.deliriumSeconds ? 'delirium' : P.infectionTime > infection.feverSeconds ? 'fever' : 'malaise'\n },\n timeLeft: () => (P.infected && infection ? Math.max(0, infection.deathSeconds - P.infectionTime) : null),\n spreadFactor() {\n const panic = P.panic > derived.composure * numbers.panicSpreadAt ? numbers.panicSpread : 1\n const fever = P.infected && infection && P.infectionTime > infection.feverSeconds ? infection.feverSpread : 1\n return panic * fever * (1 + Math.hypot(P.vx, P.vz) * numbers.moveSpread)\n },\n front,\n on(event, listener) {\n let set = listeners.get(event)\n if (!set) listeners.set(event, (set = new Set()))\n set.add(listener as (event: never) => void)\n return () => void set.delete(listener as (event: never) => void)\n },\n save: () => ({ state: structuredClone(P), attributes }),\n load(save) {\n P = structuredClone(save.state)\n },\n setWorld(next) {\n defaultWorld = next\n },\n }\n}\n","import type { KnownDeathCause, PlayerMessageId } from '../types'\n\nexport type PlayerText = Readonly<Record<PlayerMessageId | KnownDeathCause, string>>\n\n/** The game's own words (G 68434, 68452, 68518, 68525-68541, 68547) and the death causes it shows (G 68448, 68454, 68510, 68519, 68539). */\nconst PT_BR: PlayerText = {\n grabbed: 'AGARRADO! Aperte E várias vezes para empurrar ou F para a faca',\n grabbed_drown: 'O AFOGADO TE PUXA PARA O FUNDO! E várias vezes ou F para a faca',\n bitten: 'Você foi mordido. Não há cura.',\n bandaged: 'Curativo feito',\n knife_head: 'Faca na cabeça!',\n knife_miss: 'Errou a facada',\n pushed_off: 'Empurrou!',\n drowning: 'Afogando! Solte-se!',\n no_jaw: 'Sem mandíbula: só arranhou',\n stood_up: 'De pé!',\n infected: 'Morreu infectado',\n killed: 'Morto pela horda',\n bitten_to_death: 'Mordido',\n infection: 'A infecção venceu',\n bled_out: 'Sangrou até a morte',\n hunger_thirst: 'Fome e sede',\n drowned: 'Afogado',\n burned: 'Queimado',\n}\n\nconst EN: PlayerText = {\n grabbed: 'GRABBED! Press E repeatedly to push or F for the knife',\n grabbed_drown: 'THE DROWNED PULLS YOU UNDER! E repeatedly or F for the knife',\n bitten: 'You were bitten. There is no cure.',\n bandaged: 'Wound dressed',\n knife_head: 'Knife to the head!',\n knife_miss: 'The stab missed',\n pushed_off: 'Pushed off!',\n drowning: 'Drowning! Break free!',\n no_jaw: 'No jaw: only a scratch',\n stood_up: 'Back on your feet!',\n infected: 'Died infected',\n killed: 'Killed by the horde',\n bitten_to_death: 'Bitten',\n infection: 'The infection won',\n bled_out: 'Bled to death',\n hunger_thirst: 'Hunger and thirst',\n drowned: 'Drowned',\n burned: 'Burned',\n}\n\nexport const PLAYER_TEXT: Readonly<Record<'en' | 'pt-BR', PlayerText>> = { en: EN, 'pt-BR': PT_BR }\n\n/** The text of a message or death cause id in a locale (`pt-BR` or `en`, the language part is enough); unknown ids come back as they are. */\nexport const playerTextOf = (id: string, locale = 'pt-BR'): string => {\n const table = locale.toLowerCase().startsWith('en') ? EN : PT_BR\n return (table as Readonly<Record<string, string>>)[id] ?? id\n}\n","export type PlayerBenchText = {\n readonly group: string\n readonly name: string\n readonly controls: Readonly<Record<'infection' | 'agility' | 'vigor' | 'seed' | 'hurt' | 'bite' | 'grab' | 'push' | 'knife' | 'bandage' | 'knock' | 'crouch' | 'reset', string>>\n readonly hints: Readonly<Record<'infection' | 'agility' | 'vigor' | 'seed' | 'grab' | 'push', string>>\n readonly metrics: Readonly<Record<'health' | 'stamina' | 'bleeding' | 'wounds' | 'stage' | 'time_left' | 'panic' | 'spread' | 'grab' | 'noise' | 'steps' | 'message', string>>\n readonly stages: Readonly<Record<'none' | 'malaise' | 'fever' | 'delirium' | 'dead', string>>\n readonly scenarios: Readonly<Record<'stamina' | 'bleed_bandage' | 'normal_world' | 'infection_kills' | 'grab_break_free' | 'determinism', string>>\n readonly yes: string\n readonly no: string\n}\n\nconst EN: PlayerBenchText = {\n group: 'Player',\n name: 'Player area',\n controls: {\n infection: 'Individual infection',\n agility: 'Agility',\n vigor: 'Vigor',\n seed: 'Seed',\n hurt: 'Take a hit (10)',\n bite: 'Bite',\n grab: 'Get grabbed',\n push: 'Push (E)',\n knife: 'Knife (F)',\n bandage: 'Bandage (B)',\n knock: 'Knocked down 1.5 s',\n crouch: 'Crouch (C)',\n reset: 'Start again',\n },\n hints: {\n infection: 'Off: a normal world, wounds never infect. On: the game rule (scratch 6%, laceration 22%, bite 100%; fever at 30 s, death at 120 s).',\n agility: 'The sheet: stamina, run speed and footstep noise come from it.',\n vigor: 'The sheet: health, stamina and composure come from it.',\n seed: 'The same seed gives the same wounds and the same knife rolls.',\n grab: 'Something grabs you from behind: 3 s to push it off (6 pushes) or to land the knife (70%).',\n push: 'Shoves what is in front, or pushes off what holds you.',\n },\n metrics: {\n health: 'Health',\n stamina: 'Stamina',\n bleeding: 'Bleeding',\n wounds: 'Wounds',\n stage: 'Infection',\n time_left: 'Time left',\n panic: 'Panic',\n spread: 'Aim spread x',\n grab: 'Grab timer',\n noise: 'Last noise',\n steps: 'Footsteps',\n message: 'Message',\n },\n stages: { none: 'None', malaise: 'Malaise', fever: 'Fever', delirium: 'Delirium', dead: 'Dead' },\n scenarios: {\n stamina: 'Running drains stamina and resting gives it back',\n bleed_bandage: 'A laceration bleeds until it is dressed',\n normal_world: 'In a normal world a bite hurts and bleeds but never infects',\n infection_kills: 'With the infection on, a bite brings fever and kills at its time',\n grab_break_free: 'Six pushes break a grab before the bite',\n determinism: 'The same seed gives the same wounds',\n },\n yes: 'yes',\n no: 'no',\n}\n\nconst PT_BR: PlayerBenchText = {\n group: 'Jogador',\n name: 'Área do jogador',\n controls: {\n infection: 'Infecção individual',\n agility: 'Agilidade',\n vigor: 'Vigor',\n seed: 'Semente',\n hurt: 'Levar um golpe (10)',\n bite: 'Mordida',\n grab: 'Ser agarrado',\n push: 'Empurrar (E)',\n knife: 'Faca (F)',\n bandage: 'Curativo (B)',\n knock: 'Derrubado 1,5 s',\n crouch: 'Agachar (C)',\n reset: 'Recomeçar',\n },\n hints: {\n infection: 'Desligada: mundo normal, ferida nunca infecta. Ligada: a regra do jogo (arranhão 6%, laceração 22%, mordida 100%; febre aos 30 s, morte aos 120 s).',\n agility: 'A ficha: fôlego, velocidade de corrida e ruído dos passos saem dela.',\n vigor: 'A ficha: vida, fôlego e compostura saem dela.',\n seed: 'A mesma semente dá as mesmas feridas e os mesmos golpes de faca.',\n grab: 'Algo te agarra por trás: 3 s para empurrar (6 empurrões) ou acertar a faca (70%).',\n push: 'Empurra o que está na frente, ou se solta do que te segura.',\n },\n metrics: {\n health: 'Vida',\n stamina: 'Fôlego',\n bleeding: 'Sangrando',\n wounds: 'Feridas',\n stage: 'Infecção',\n time_left: 'Tempo restante',\n panic: 'Pânico',\n spread: 'Dispersão x',\n grab: 'Agarrão',\n noise: 'Último ruído',\n steps: 'Passos',\n message: 'Mensagem',\n },\n stages: { none: 'Nenhuma', malaise: 'Mal-estar', fever: 'Febre', delirium: 'Delírio', dead: 'Morto' },\n scenarios: {\n stamina: 'Correr gasta fôlego e descansar devolve',\n bleed_bandage: 'Uma laceração sangra até o curativo',\n normal_world: 'No mundo normal a mordida machuca e sangra, mas não infecta',\n infection_kills: 'Com a infecção ligada, a mordida dá febre e mata no tempo dela',\n grab_break_free: 'Seis empurrões soltam o agarrão antes da mordida',\n determinism: 'A mesma semente dá as mesmas feridas',\n },\n yes: 'sim',\n no: 'não',\n}\n\nexport const playerBenchTextOf = (locale: string): PlayerBenchText => (locale.toLowerCase().startsWith('en') ? EN : PT_BR)\n","import type { BenchChange, ModuleControl, ModuleHost, ModuleMetric, ModuleScenario, TestableModule } from '@adatechnology/game-contracts'\n\nimport { playerTextOf } from '../locales'\nimport { createPlayer } from '../player'\nimport type { Player, PlayerOptions } from '../player'\nimport type { PlayerAction, PlayerCrowd, PlayerInput } from '../types'\nimport { playerBenchTextOf } from './locale'\n\nexport type PlayerTestModuleOptions = PlayerOptions & { readonly locale?: string }\n\n/** What the scenarios use of the context the test room passes. */\nexport interface PlayerScenarioLike {\n expect(condition: boolean, label: string, data?: Record<string, unknown>): void\n}\n\nexport type PlayerTestModule = TestableModule<PlayerScenarioLike> & {\n /** The player in use (replaced when the bench changes the sheet, the seed or the infection). */\n readonly player: Player\n}\n\ntype CameraLike = { position: { x: number; y: number; z: number }; rotation?: { y: number }; getWorldDirection?(target: unknown): { x: number; z: number } }\ntype ThreeLike = { Vector3?: new () => { x: number; y: number; z: number } }\n\nconst MOVING_SPEED = 0.2\nconst SPRINT_SPEED = 3.4\nconst FRAME = 1 / 30\n\n/**\n * One agent standing behind the player for the grab test: the bench has no crowd, so this is the hand that holds. It follows `hold`, takes\n * the shove and the knife, and leaves the count once it lets go.\n */\nconst createGrabber = () => {\n const agent = { x: 0, z: 0, on: false, stunned: 0, hits: 0 }\n const crowd: PlayerCrowd = {\n count: () => (agent.on ? 1 : 0),\n active: () => agent.on,\n x: () => agent.x,\n z: () => agent.z,\n y: () => 0,\n floor: () => 0,\n chasing: () => agent.on,\n down: () => agent.stunned > 0,\n hold(_i, x, z, k) {\n agent.x += (x - agent.x) * k\n agent.z += (z - agent.z) * k\n },\n stun(_i, seconds) {\n agent.stunned = seconds\n agent.on = false\n },\n chase() {\n agent.on = false\n },\n damage() {\n agent.hits += 1\n agent.on = false\n },\n }\n return { agent, crowd }\n}\n\n/**\n * The player area of a test room, against the generic contracts only. The room's camera is the player: where it walks, the player walks; its speed\n * decides walking or running, so stamina, footsteps and their noise follow the viewer. The bench hurts, bites, grabs and knocks the player down,\n * switches the individual infection (off by default: a normal world) and sets the sheet. Footsteps and flesh sounds go to `host.audio`.\n */\nexport function createPlayerTestModule(options: PlayerTestModuleOptions = {}): PlayerTestModule {\n const locale = options.locale ?? 'pt-BR'\n const text = playerBenchTextOf(locale)\n const { locale: _locale, ...playerOptions } = options\n void _locale\n const settings = { infection: options.infection === undefined ? false : options.infection !== false, agility: options.attributes?.agility ?? 5, vigor: options.attributes?.vigor ?? 5, seed: options.seed ?? 1 }\n let host: ModuleHost | null = null\n const grabber = createGrabber()\n let lastNoise = 0\n let steps = 0\n let lastMessage = ''\n let pending: Partial<Record<PlayerAction, boolean>> = {}\n let bandage = false\n let last: { x: number; z: number } | null = null\n const offs: (() => void)[] = []\n\n const build = (): Player => {\n for (const off of offs.splice(0)) off()\n const made = createPlayer({ ...playerOptions, seed: settings.seed, infection: settings.infection, attributes: { ...playerOptions.attributes, agility: settings.agility, vigor: settings.vigor } })\n offs.push(made.on('noise', (e) => void (lastNoise = e.radius)))\n offs.push(made.on('step', () => void (steps += 1)))\n offs.push(made.on('message', (e) => void (lastMessage = playerTextOf(e.id, locale))))\n offs.push(made.on('sound', (e) => void host?.audio?.play({ sound: e.sound, volume: e.volume, position: e.position })))\n offs.push(made.on('died', (e) => host?.log(`player died: ${e.cause}`, { cause: e.cause })))\n lastNoise = 0\n steps = 0\n lastMessage = ''\n return made\n }\n let player = build()\n\n const view = (): { x: number; z: number; yaw: number } | null => {\n const camera = host?.camera as CameraLike | undefined\n if (!camera?.position) return null\n const Vector3 = (host?.THREE as ThreeLike | undefined)?.Vector3\n if (camera.getWorldDirection && Vector3) {\n const look = camera.getWorldDirection(new Vector3())\n return { x: camera.position.x, z: camera.position.z, yaw: Math.atan2(-look.x, -look.z) }\n }\n return { x: camera.position.x, z: camera.position.z, yaw: camera.rotation?.y ?? 0 }\n }\n\n const frame = (dt: number): void => {\n const here = view()\n const speed = here && last && dt > 0 ? Math.hypot(here.x - last.x, here.z - last.z) / dt : 0\n if (here) {\n player.state.x = here.x\n player.state.z = here.z\n }\n const input: PlayerInput = { forward: speed > MOVING_SPEED ? 1 : 0, run: speed > SPRINT_SPEED, yaw: here?.yaw ?? 0, bandage, pressed: pending }\n pending = {}\n bandage = false\n player.update(dt, input, { crowd: grabber.crowd })\n if (here) {\n player.state.x = here.x\n player.state.z = here.z\n last = { x: here.x, z: here.z }\n }\n if (grabber.agent.stunned > 0) grabber.agent.stunned = Math.max(0, grabber.agent.stunned - dt)\n }\n\n const grab = (): void => {\n const P = player.state\n grabber.agent.on = true\n grabber.agent.x = P.x - Math.sin(P.yaw) * player.numbers.grabOffset\n grabber.agent.z = P.z - Math.cos(P.yaw) * player.numbers.grabOffset\n player.grab(0)\n }\n\n const onChange = (change: BenchChange): void => {\n if (change.kind === 'action') {\n const id = change.id\n if (id === 'hurt') player.hurt(10)\n else if (id === 'bite') player.bite()\n else if (id === 'grab') grab()\n else if (id === 'knock') player.knock(1.5)\n else if (id === 'bandage') bandage = true\n else if (id === 'push' || id === 'knife' || id === 'crouch') pending = { ...pending, [id]: true }\n else if (id === 'reset') player = build()\n return\n }\n if (change.kind !== 'control') return\n const { id, value } = change\n if (id === 'infection' && typeof value === 'boolean' && value !== settings.infection) settings.infection = value\n else if ((id === 'agility' || id === 'vigor' || id === 'seed') && typeof value === 'number' && value !== settings[id]) settings[id] = value\n else return\n player = build()\n }\n\n const controls = (): ModuleControl[] => [\n { kind: 'boolean', id: 'infection', name: text.controls.infection, hint: text.hints.infection, default: settings.infection },\n { kind: 'number', id: 'agility', name: text.controls.agility, hint: text.hints.agility, min: 1, max: 8, step: 1, default: settings.agility },\n { kind: 'number', id: 'vigor', name: text.controls.vigor, hint: text.hints.vigor, min: 1, max: 8, step: 1, default: settings.vigor },\n { kind: 'number', id: 'seed', name: text.controls.seed, hint: text.hints.seed, min: 1, max: 9999, step: 1, default: settings.seed },\n { kind: 'action', id: 'hurt', name: text.controls.hurt },\n { kind: 'action', id: 'bite', name: text.controls.bite },\n { kind: 'action', id: 'grab', name: text.controls.grab, hint: text.hints.grab },\n { kind: 'action', id: 'push', name: text.controls.push, hint: text.hints.push },\n { kind: 'action', id: 'knife', name: text.controls.knife },\n { kind: 'action', id: 'bandage', name: text.controls.bandage },\n { kind: 'action', id: 'knock', name: text.controls.knock },\n { kind: 'action', id: 'crouch', name: text.controls.crouch },\n { kind: 'action', id: 'reset', name: text.controls.reset },\n ]\n\n const stageName = (): string => (player.state.alive ? text.stages[player.stage()] : text.stages.dead)\n const metrics = (): ModuleMetric[] => [\n { id: 'health', name: text.metrics.health, digits: 1, max: player.derived.maxHealth, read: () => Math.max(0, player.state.health) },\n { id: 'stamina', name: text.metrics.stamina, digits: 1, max: player.derived.maxStamina, read: () => player.state.stamina },\n { id: 'bleeding', name: text.metrics.bleeding, read: () => (player.state.bleeding ? text.yes : text.no) },\n { id: 'wounds', name: text.metrics.wounds, digits: 0, read: () => player.state.wounds.length },\n { id: 'stage', name: text.metrics.stage, read: stageName },\n { id: 'time_left', name: text.metrics.time_left, unit: 's', digits: 0, read: () => player.timeLeft() ?? 0 },\n { id: 'panic', name: text.metrics.panic, digits: 1, read: () => player.state.panic },\n { id: 'spread', name: text.metrics.spread, digits: 2, read: () => player.spreadFactor() },\n { id: 'grab_timer', name: text.metrics.grab, unit: 's', digits: 1, read: () => (player.state.grabbedBy >= 0 ? player.state.grabTimer : 0) },\n { id: 'noise', name: text.metrics.noise, unit: 'm', digits: 1, read: () => lastNoise },\n { id: 'steps', name: text.metrics.steps, digits: 0, read: () => steps },\n { id: 'message', name: text.metrics.message, read: () => lastMessage },\n ]\n\n // each scenario runs its own player, so the bench's live one is not touched\n const fresh = (extra: PlayerOptions = {}): Player => createPlayer({ ...playerOptions, ...extra })\n const run = (made: Player, seconds: number, input: PlayerInput = {}, crowd?: PlayerCrowd): void => {\n for (let t = 0; t < seconds; t += FRAME) made.update(FRAME, input, crowd ? { crowd } : undefined)\n }\n const scenarios = (): Array<ModuleScenario<PlayerScenarioLike>> => [\n {\n id: 'player_stamina',\n name: text.scenarios.stamina,\n run: ({ expect }) => {\n const made = fresh({ seed: 1 })\n const full = made.state.stamina\n run(made, 4, { forward: 1, run: true })\n const tired = made.state.stamina\n expect(tired < full - 40, 'four seconds of running spend 48 of stamina', { full, tired })\n run(made, 3)\n expect(made.state.stamina > tired, 'standing still gives it back', { tired, rested: made.state.stamina })\n },\n },\n {\n id: 'player_bleed_bandage',\n name: text.scenarios.bleed_bandage,\n run: ({ expect }) => {\n const made = fresh({ seed: 1 })\n made.bite()\n const after = made.state.health\n run(made, 2)\n expect(made.state.bleeding === 1 && made.state.health < after, 'the wound bleeds', { health: made.state.health })\n run(made, FRAME, { bandage: true })\n const dressed = made.state.health\n run(made, 2)\n expect(made.state.bleeding === 0 && made.state.health === dressed, 'dressed, it stops', { health: made.state.health })\n },\n },\n {\n id: 'player_normal_world',\n name: text.scenarios.normal_world,\n run: ({ expect }) => {\n const made = fresh({ seed: 1, infection: false })\n made.bite()\n run(made, 10)\n expect(!made.state.infected && made.state.health < made.derived.maxHealth, 'bitten, hurt, not infected', { health: made.state.health })\n },\n },\n {\n id: 'player_infection_kills',\n name: text.scenarios.infection_kills,\n run: ({ expect }) => {\n const made = fresh({ seed: 1, infection: true })\n made.bite()\n run(made, FRAME, { bandage: true })\n run(made, 40)\n expect(made.stage() === 'fever', 'fever after 30 s', { stage: made.stage() })\n run(made, 90)\n expect(!made.state.alive && made.state.cause === 'infection', 'dead at 120 s', { cause: made.state.cause })\n },\n },\n {\n id: 'player_grab_break_free',\n name: text.scenarios.grab_break_free,\n run: ({ expect }) => {\n const made = fresh({ seed: 1 })\n const { agent, crowd } = createGrabber()\n agent.on = true\n made.grab(0)\n for (let push = 0; push < 6; push++) {\n made.update(FRAME, { pressed: { push: true } }, { crowd })\n made.update(FRAME, {}, { crowd })\n }\n expect(made.state.grabbedBy === -1 && made.state.wounds.length === 0, 'free, and no bite', { grabbedBy: made.state.grabbedBy })\n },\n },\n {\n id: 'player_determinism',\n name: text.scenarios.determinism,\n run: ({ expect }) => {\n const wounds = (seed: number): string => {\n const made = fresh({ seed })\n for (let k = 0; k < 12; k++) made.hurt(1)\n return made.state.wounds.join(',')\n }\n expect(wounds(4) === wounds(4), 'the same seed gives the same wounds')\n expect(wounds(4) !== wounds(5), 'another seed gives others')\n },\n },\n ]\n\n const module: PlayerTestModule = {\n id: 'player_area',\n name: text.name,\n group: text.group,\n get player() {\n return player\n },\n items: () => [],\n controls: () => controls(),\n metrics: () => metrics(),\n scenarios: () => scenarios(),\n attach(lent) {\n host = lent\n last = null\n const off = lent.bench?.onChange(onChange)\n const offFrame = lent.onFrame(frame)\n return () => {\n off?.()\n offFrame()\n host = null\n }\n },\n }\n return module\n}\n"],"mappings":"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","names":["EN","PT_BR","id"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/data/defaults.json","../src/rng.ts","../src/player.ts","../src/furniture-push.ts","../src/locales/index.ts","../src/bench/locale.ts","../src/bench/module.ts"],"sourcesContent":["export { PLAYER_DEFAULTS, createPlayer, deriveVitals, drawWound } from './player'\nexport type { Player, PlayerOptions } from './player'\nexport { createRng } from './rng'\nexport { FURNITURE_PUSH_DEFAULTS, canPush, createFurniturePush, gripSecondsFor, pushSpeedFor } from './furniture-push'\nexport type { FurniturePush, FurniturePushBlock, FurniturePushInput, FurniturePushPhase, FurniturePushRules, FurniturePushStep, FurniturePushTarget } from './furniture-push'\nexport { PLAYER_TEXT, playerTextOf } from './locales'\nexport type { PlayerText } from './locales'\nexport { createPlayerTestModule } from './bench/module'\nexport type { PlayerTestModule, PlayerTestModuleOptions } from './bench/module'\nexport type * from './types'\n","{\n \"sources\": {\n \"game\": \"specs/001-migracao-entregas-dos-times/artefatos/2UG1Mhe9LqJkQKKVsJkTWR/jogo.js\",\n \"attributes\": \"G 62004 FICHA (Personagens 3.2: every attribute 5, no traits)\",\n \"derived\": \"G 62005-62012 DERIV\",\n \"wounds\": \"G 62016 FERIDA (Personagens 3.7): share of each wound kind, and its infection chance (used only when an infection rule is on)\",\n \"infection\": \"G 62015 INFEC (the slice's accelerated clock: fever 30 s, delirium 70 s, death 120 s, reanimation 8 s after); G 68509 fever noise\",\n \"numbers\": \"G 68427-68640 player, playerUpdate, frontZombies, shove, knife; G 68678-68681 the aim spread modifiers; G 65507 walkCad\"\n },\n \"attributes\": { \"strength\": 5, \"vigor\": 5, \"agility\": 5, \"perception\": 5, \"intellect\": 5, \"presence\": 5 },\n \"derived\": {\n \"maxHealth\": { \"base\": 70, \"terms\": [[\"vigor\", 6]] },\n \"maxStamina\": { \"base\": 40, \"terms\": [[\"vigor\", 6], [\"agility\", 4]] },\n \"runSpeed\": { \"base\": 5.2, \"terms\": [[\"agility\", 0.12]] },\n \"walkSpeed\": { \"base\": 1.6, \"terms\": [] },\n \"footstepNoise\": { \"base\": 100, \"terms\": [[\"agility\", -4]], \"divide\": 100 },\n \"composure\": { \"base\": 20, \"terms\": [[\"vigor\", 3], [\"presence\", 4]] }\n },\n \"wounds\": {\n \"scratch\": { \"share\": 0.6, \"infectionChance\": 0.06, \"bleeds\": false },\n \"laceration\": { \"share\": 0.3, \"infectionChance\": 0.22, \"bleeds\": true },\n \"bite\": { \"share\": 0.1, \"infectionChance\": 1, \"bleeds\": true }\n },\n \"infection\": {\n \"feverSeconds\": 30,\n \"deliriumSeconds\": 70,\n \"deathSeconds\": 120,\n \"reanimateSeconds\": 8,\n \"feverNoiseEvery\": 2,\n \"feverNoiseChance\": 0.5,\n \"feverNoiseRadius\": 10,\n \"feverNoiseVolume\": 2,\n \"feverSpeed\": 0.85,\n \"feverSpread\": 1.5\n },\n \"numbers\": {\n \"hurtFlash\": 0.4,\n \"hurtVolume\": 0.8,\n \"biteDamage\": 25,\n \"biteFlash\": 0.8,\n \"biteVolume\": 1.2,\n \"burnPerSecond\": 3,\n \"bleedPerSecond\": 0.15,\n \"grabSeconds\": 3,\n \"grabVolume\": 1,\n \"grabFollow\": 12,\n \"grabOffset\": 0.55,\n \"grabPushCost\": 6,\n \"grabPushMinStamina\": 5,\n \"grabPushVolume\": 1.5,\n \"grabPushes\": 6,\n \"grabPushStun\": 1.2,\n \"grabPushSpeed\": 3,\n \"grabKnifeChance\": 0.7,\n \"grabKnifeRegion\": 0,\n \"grabKnifeDamage\": 22,\n \"grabKnifeDistance\": 0.5,\n \"grabKnifeCut\": 0.7,\n \"drownDamage\": 30,\n \"drownFlash\": 0.8,\n \"noJawDamage\": 8,\n \"grabAttackCooldown\": 2,\n \"vaultSeconds\": 0.7,\n \"vaultCost\": 15,\n \"vaultHeight\": 1.9,\n \"vaultScanFrom\": 0.3,\n \"vaultScanTo\": 1.0,\n \"vaultScanStep\": 0.1,\n \"vaultLandFrom\": 0.4,\n \"vaultLandTo\": 1.4,\n \"vaultClearance\": 0.3,\n \"vaultCheckHeight\": 0.4,\n \"vaultNoise\": 6,\n \"vaultStartVolume\": 0.8,\n \"vaultLandVolume\": 1,\n \"crouchSpeed\": 1.0,\n \"walkFactor\": 1.35,\n \"aimSpeedCap\": 1.4,\n \"waterSpeed\": 0.55,\n \"runMinStamina\": 1,\n \"runDrain\": 12,\n \"regenMoving\": 4,\n \"regenStill\": 8,\n \"acceleration\": 10,\n \"radius\": 0.3,\n \"blockHeight\": 0.4,\n \"pushApartRadius\": 0.55,\n \"pushApartHeight\": 1.2,\n \"hipFollow\": 10,\n \"hipMinSpeed\": 0.3,\n \"hipLimit\": 0.9,\n \"backwardsBelow\": -0.1,\n \"cadenceBase\": 0.5,\n \"cadencePerSpeed\": 0.3,\n \"cadenceMinSpeed\": 0.05,\n \"turnFollow\": 12,\n \"stepEvery\": 0.75,\n \"stepMinSpeed\": 0.3,\n \"stepNoiseRun\": 8,\n \"stepNoiseWalk\": 3,\n \"stepNoiseCrouch\": 1,\n \"stepNoiseWater\": 2,\n \"stepVolumeRun\": 0.6,\n \"stepVolumeWalk\": 0.3,\n \"shoveCost\": 10,\n \"shoveVolume\": 1.2,\n \"shoveRange\": 1.6,\n \"shoveCone\": 0.3,\n \"shoveStun\": 0.9,\n \"shoveSpeed\": 2.5,\n \"meleeMinStamina\": 5,\n \"meleeCostLight\": 5,\n \"meleeCostHeavy\": 12,\n \"meleeHeavyKg\": 1.5,\n \"meleeVolume\": 0.6,\n \"meleeRangeBase\": 0.9,\n \"meleeCone\": 0.5,\n \"meleeHeadChance\": 0.35,\n \"meleeArmChance\": 0.5,\n \"meleeStrengthPerPoint\": 0.06,\n \"meleeStrengthBase\": 5,\n \"meleeCritToCut\": 60,\n \"panicGain\": 1.2,\n \"panicDecay\": 3,\n \"panicMax\": 100,\n \"panicSpreadAt\": 0.6,\n \"panicSpread\": 1.4,\n \"moveSpread\": 0.4\n },\n \"fist\": { \"damage\": 8, \"crit\": 0, \"reach\": 0.5, \"noise\": 1 }\n}\n","const FNV_OFFSET = 0x811c9dc5\nconst FNV_PRIME = 0x01000193\nconst MIX = 0x9e3779b1\n\n/** Deterministic mulberry32 generator; returns floats in [0, 1). */\nexport function 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/** A seed for the stream called `name`: the same seed gives each name its own sequence, so lightning never shifts the schedule. */\nexport function streamSeed(seed: number, name: string): number {\n let hash = FNV_OFFSET\n for (let index = 0; index < name.length; index++) hash = Math.imul(hash ^ name.charCodeAt(index), FNV_PRIME) >>> 0\n return Math.imul((seed >>> 0) ^ hash, MIX) >>> 0\n}\n\nexport function createStream(seed: number, name: string): () => number {\n return createRng(streamSeed(seed, name))\n}\n\nexport function drawBetween(rng: () => number, range: readonly [min: number, max: number]): number {\n return range[0] + rng() * (range[1] - range[0])\n}\n","import defaults from './data/defaults.json'\nimport { createRng } from './rng'\nimport type {\n Attributes,\n DeathCause,\n Derived,\n DerivedFormulas,\n DerivedId,\n InfectionRule,\n LinearFormula,\n MeleeItem,\n PlayerAction,\n PlayerCrowd,\n PlayerEventMap,\n PlayerEventName,\n PlayerInput,\n PlayerMessageId,\n PlayerNumbers,\n PlayerSave,\n PlayerSoundId,\n PlayerState,\n PlayerWorld,\n WoundTable,\n} from './types'\n\nexport const PLAYER_DEFAULTS = defaults as unknown as {\n readonly sources: Readonly<Record<string, string>>\n readonly attributes: Attributes\n readonly derived: DerivedFormulas\n readonly wounds: WoundTable\n readonly infection: InfectionRule\n readonly numbers: PlayerNumbers\n readonly fist: MeleeItem\n}\n\nexport type PlayerOptions = {\n /** The random stream (the game passes its single stream). Default `createRng(seed)`. */\n readonly random?: () => number\n readonly seed?: number\n /** The sheet: every attribute 5 by default. */\n readonly attributes?: Partial<Attributes>\n readonly derived?: Partial<DerivedFormulas>\n readonly wounds?: WoundTable\n /** An individual infection (`true` uses the defaults; an object patches them). Off by default: the normal world comes first. */\n readonly infection?: boolean | Partial<InfectionRule>\n readonly numbers?: Partial<PlayerNumbers>\n readonly fist?: MeleeItem\n readonly position?: { readonly x?: number; readonly z?: number; readonly yaw?: number }\n readonly world?: PlayerWorld\n}\n\nexport type Player = {\n readonly state: PlayerState\n readonly attributes: Attributes\n readonly derived: Derived\n readonly numbers: PlayerNumbers\n readonly infection: InfectionRule | null\n update(dt: number, input?: PlayerInput, world?: PlayerWorld): void\n /** A hit that opens a wound (drawn from the wound table) and may infect. `by` is the agent that hit, if any. */\n hurt(amount: number, by?: number): void\n /** A bite: damage, bleeding, a bite wound and (with an infection rule) the infection. */\n bite(by?: number): void\n grab(by: number, noJaw?: boolean, drown?: boolean): void\n release(): void\n knock(seconds: number): void\n infect(source: string): void\n /** Kills the player with a cause (the host's deaths: a fall, a fire). */\n die(cause: DeathCause): void\n /** Infection stage: `none`, `malaise`, `fever`, `delirium`. */\n stage(): 'none' | 'malaise' | 'fever' | 'delirium'\n /** Seconds the infection has left, or null. */\n timeLeft(): number | null\n /** What the player's state does to aim spread (panic, fever, moving); the weapon multiplies its own spread by it. */\n spreadFactor(): number\n /** The agents in front (nearest first) within `range` m and a cone of `cosMin`, as `[distance, index]`. */\n front(range: number, cosMin: number, yaw: number, crowd?: PlayerCrowd): [number, number][]\n on<K extends PlayerEventName>(event: K, listener: (event: PlayerEventMap[K]) => void): () => void\n save(): PlayerSave\n load(save: PlayerSave): void\n /** The world `update` uses when it is given none. */\n setWorld(world: PlayerWorld): void\n}\n\nconst TAU_APPROX = 6.2832\n\nconst evaluate = (formula: LinearFormula, attributes: Attributes): number => {\n let value = formula.base\n for (const [attribute, coefficient] of formula.terms) value += coefficient * attributes[attribute]\n return formula.divide === undefined ? value : value / formula.divide\n}\n\n/** The derived values of a sheet (the game's `DERIV`). */\nexport const deriveVitals = (attributes: Attributes, formulas: DerivedFormulas = PLAYER_DEFAULTS.derived): Derived => {\n const out = {} as Record<DerivedId, number>\n for (const id of Object.keys(formulas) as DerivedId[]) out[id] = evaluate(formulas[id], attributes)\n return out\n}\n\n/** Which wound a hit opens: one draw, the kinds in the listed order, the last one takes the rest (the game's `FERIDA` draw). */\nexport const drawWound = (wounds: WoundTable, random: () => number): string => {\n const kinds = Object.keys(wounds)\n const draw = random()\n let acc = 0\n for (let k = 0; k < kinds.length - 1; k++) {\n acc += wounds[kinds[k]!]!.share\n if (draw < acc) return kinds[k]!\n }\n return kinds[kinds.length - 1]!\n}\n\nconst clamp = (v: number, a: number, b: number): number => (v < a ? a : v > b ? b : v)\nconst lerp = (a: number, b: number, t: number): number => a + (b - a) * t\n\nconst freshState = (derived: Derived, position: PlayerOptions['position']): PlayerState => ({\n x: position?.x ?? 0,\n z: position?.z ?? 0,\n y: 0,\n vx: 0,\n vz: 0,\n yaw: position?.yaw ?? 0,\n floor: 0,\n alive: true,\n turned: false,\n health: derived.maxHealth,\n stamina: derived.maxStamina,\n crouch: false,\n running: false,\n stepTimer: 0,\n phase: 0,\n hip: 0,\n grabbedBy: -1,\n grabTimer: 0,\n grabPushes: 0,\n grabNoJaw: false,\n grabDrown: false,\n infected: false,\n infectionTime: 0,\n infectionSource: '',\n wounds: [],\n bleeding: 0,\n blind: 0,\n screamBoost: 0,\n panic: 0,\n hurtFlash: 0,\n deathTime: 0,\n cause: '',\n downTimer: 0,\n burnTimer: 0,\n scentTimer: 0,\n vaultTimer: 0,\n vault: null,\n})\n\n/**\n * The player body: a literal port of the team game's `player` and `playerUpdate` (G 68427-68640) with the world, the crowd and the input as\n * arguments instead of globals. The draws on `random` happen in the game's order (wound kind, infection, the fever cough, the knife when grabbed,\n * the melee region), so a game that passes its own stream keeps its sequence.\n */\nexport function createPlayer(options: PlayerOptions = {}): Player {\n const random = options.random ?? createRng(options.seed ?? 1)\n const attributes: Attributes = { ...PLAYER_DEFAULTS.attributes, ...options.attributes }\n const formulas: DerivedFormulas = { ...PLAYER_DEFAULTS.derived, ...options.derived }\n const derived = deriveVitals(attributes, formulas)\n const numbers: PlayerNumbers = { ...PLAYER_DEFAULTS.numbers, ...options.numbers }\n const wounds = options.wounds ?? PLAYER_DEFAULTS.wounds\n const infection: InfectionRule | null =\n options.infection === undefined || options.infection === false ? null : options.infection === true ? PLAYER_DEFAULTS.infection : { ...PLAYER_DEFAULTS.infection, ...options.infection }\n const fist = options.fist ?? PLAYER_DEFAULTS.fist\n const listeners = new Map<PlayerEventName, Set<(event: never) => void>>()\n let P = freshState(derived, options.position)\n let defaultWorld: PlayerWorld = options.world ?? {}\n let world: PlayerWorld = defaultWorld\n\n const emit = <K extends PlayerEventName>(event: K, payload: PlayerEventMap[K]): void => {\n const set = listeners.get(event)\n if (set) for (const listener of set) (listener as (event: PlayerEventMap[K]) => void)(payload)\n }\n const sound = (id: PlayerSoundId, volume: number): void => emit('sound', { sound: id, volume, position: [P.x, P.y, P.z] })\n const noise = (x: number, z: number, radius: number): void => emit('noise', { x, z, radius })\n const message = (id: PlayerMessageId | DeathCause, seconds: number): void => emit('message', { id, seconds })\n const inWater = (x: number, z: number): boolean => world.inWater?.(x, z) ?? false\n const solidAt = (x: number, z: number, y: number): boolean => world.solidAt?.(x, z, y) ?? false\n const cellKind = (x: number, z: number): number => world.cellKind?.(x, z) ?? 0\n const blocked = (x: number, z: number): boolean => (world.blocked ? world.blocked(x, z) : solidAt(x, z, numbers.blockHeight))\n const chanceOf = (kind: string): number => infection?.chances?.[kind] ?? wounds[kind]?.infectionChance ?? 0\n\n const die = (cause: DeathCause): void => {\n if (!P.alive) return\n P.alive = false\n P.cause = cause\n P.deathTime = 0\n P.grabbedBy = -1\n message(cause, 6)\n emit('died', { cause })\n }\n const infect = (source: string): void => {\n if (P.infected || !infection) return\n P.infected = true\n P.infectionTime = 0\n P.infectionSource = source\n emit('infected', { source })\n }\n const release = (how: PlayerEventMap['released']['how'] = 'free'): void => {\n const by = P.grabbedBy\n P.grabbedBy = -1\n if (by >= 0) emit('released', { by, how })\n }\n const hurt = (amount: number): void => {\n if (!P.alive) return\n P.health -= amount\n P.hurtFlash = numbers.hurtFlash\n sound('flesh', numbers.hurtVolume)\n const kind = drawWound(wounds, random)\n P.wounds.push(kind)\n if (wounds[kind]?.bleeds) P.bleeding = 1\n emit('hurt', { amount, wound: kind })\n if (infection && !P.infected && random() < chanceOf(kind)) infect(kind)\n if (P.health <= 0) die(P.infected ? 'infected' : 'killed')\n }\n const bite = (): void => {\n P.health -= numbers.biteDamage\n P.hurtFlash = numbers.biteFlash\n P.bleeding = 1\n P.wounds.push('bite')\n sound('flesh', numbers.biteVolume)\n emit('hurt', { amount: numbers.biteDamage, wound: 'bite' })\n infect('bite')\n message('bitten', 5)\n if (P.health <= 0) die('bitten_to_death')\n }\n const grab = (by: number, noJaw = false, drown = false): void => {\n P.grabbedBy = by\n P.grabTimer = numbers.grabSeconds\n P.grabPushes = 0\n P.grabNoJaw = noJaw\n P.grabDrown = drown\n message(drown ? 'grabbed_drown' : 'grabbed', 3)\n sound('flesh', numbers.grabVolume)\n emit('grabbed', { by, noJaw, drown })\n }\n\n const front = (range: number, cosMin: number, yaw: number, crowd: PlayerCrowd | undefined = world.crowd): [number, number][] => {\n const out: [number, number][] = []\n if (!crowd) return out\n const fx = -Math.sin(yaw)\n const fz = -Math.cos(yaw)\n const n = crowd.count()\n for (let i = 0; i < n; i++) {\n if (!crowd.active(i) || crowd.floor(i) !== P.floor) continue\n const ex = crowd.x(i) - P.x\n const ez = crowd.z(i) - P.z\n const d = Math.hypot(ex, ez)\n if (d < range && (ex * fx + ez * fz) / (d || 1) > cosMin) out.push([d, i])\n }\n return out.sort((a, b) => a[0] - b[0])\n }\n\n const shove = (yaw: number): void => {\n sound('step', numbers.shoveVolume)\n const crowd = world.crowd\n const targets: number[] = []\n for (const [d, i] of front(numbers.shoveRange, numbers.shoveCone, yaw)) {\n crowd!.stun(i, numbers.shoveStun, ((crowd!.x(i) - P.x) / d) * numbers.shoveSpeed, ((crowd!.z(i) - P.z) / d) * numbers.shoveSpeed)\n targets.push(i)\n }\n emit('shove', { targets })\n }\n\n const melee = (item: MeleeItem, yaw: number): void => {\n const t = front(numbers.meleeRangeBase + (item.reach ?? 0), numbers.meleeCone, yaw)[0]\n sound('flesh', numbers.meleeVolume)\n noise(P.x, P.z, item.noise || 1)\n if (!t) return\n const crowd = world.crowd!\n const i = t[1]\n // a blow to the head is x3 in melee; on the ground or crawling it is an execution\n const region = crowd.down(i) ? 0 : random() < numbers.meleeHeadChance ? 0 : random() < numbers.meleeArmChance ? 1 : 2 + Math.floor(random() * 2)\n const damage = item.damage * (1 + (attributes.strength - numbers.meleeStrengthBase) * numbers.meleeStrengthPerPoint)\n const cut = Math.min(1, (item.crit || 0) / numbers.meleeCritToCut)\n crowd.damage(i, { region, amount: damage, distance: t[0], cut })\n emit('melee', { target: i, region, damage, distance: t[0], cut })\n }\n\n const update = (dt: number, input: PlayerInput = {}, frameWorld?: PlayerWorld): void => {\n world = frameWorld ?? defaultWorld\n if (!P.alive) {\n P.deathTime += dt\n if (P.infected && infection && !P.turned && P.deathTime >= infection.reanimateSeconds) {\n P.turned = true\n emit('turned', { x: P.x, z: P.z, floor: P.floor })\n }\n return\n }\n const pressed: Partial<Record<PlayerAction, boolean>> = { ...input.pressed }\n const wasPressed = (action: PlayerAction): boolean => {\n const v = pressed[action] === true\n pressed[action] = false\n return v\n }\n const viewYaw = input.yaw ?? 0\n const crowd = world.crowd\n P.screamBoost = Math.max(0, P.screamBoost - dt)\n P.blind = Math.max(0, P.blind - dt)\n P.hurtFlash = Math.max(0, P.hurtFlash - dt)\n // infection on its own clock\n if (P.infected && infection) {\n const before = P.infectionTime\n P.infectionTime += dt\n if (before <= infection.feverSeconds && P.infectionTime > infection.feverSeconds) emit('stage', { stage: 'fever' })\n if (before <= infection.deliriumSeconds && P.infectionTime > infection.deliriumSeconds) emit('stage', { stage: 'delirium' })\n const every = 1 / infection.feverNoiseEvery\n if (P.infectionTime > infection.feverSeconds && Math.floor(P.infectionTime * every) !== Math.floor((P.infectionTime - dt) * every) && random() < infection.feverNoiseChance) {\n noise(P.x, P.z, infection.feverNoiseRadius)\n sound('step', infection.feverNoiseVolume)\n }\n if (P.infectionTime > infection.deathSeconds) {\n P.health = 0\n die('infection')\n return\n }\n }\n if (P.burnTimer > 0) {\n P.burnTimer -= dt\n P.health -= numbers.burnPerSecond * dt\n if (inWater(P.x, P.z)) P.burnTimer = 0\n }\n P.scentTimer = Math.max(0, P.scentTimer - dt)\n if (P.bleeding) {\n P.health -= dt * numbers.bleedPerSecond\n if (input.bandage && P.bleeding) {\n P.bleeding = 0\n message('bandaged', 2)\n }\n }\n if (P.health <= 0) {\n die(P.infected ? 'infected' : P.bleeding ? 'bled_out' : 'hunger_thirst')\n return\n }\n // grabbed: seconds to react\n if (P.grabbedBy >= 0) {\n const i = P.grabbedBy\n P.grabTimer -= dt\n if (crowd) {\n const k = 1 - Math.exp(-dt * numbers.grabFollow) // glued to the body without a jump\n crowd.hold(i, P.x - Math.sin(P.yaw) * numbers.grabOffset, P.z - Math.cos(P.yaw) * numbers.grabOffset, k, P.x, P.z)\n }\n if (wasPressed('push') && P.stamina > numbers.grabPushMinStamina) {\n P.grabPushes++\n P.stamina -= numbers.grabPushCost\n sound('step', numbers.grabPushVolume)\n }\n if (wasPressed('knife')) {\n if (random() < numbers.grabKnifeChance) {\n crowd?.damage(i, { region: numbers.grabKnifeRegion, amount: numbers.grabKnifeDamage, distance: numbers.grabKnifeDistance, cut: numbers.grabKnifeCut })\n message('knife_head', 1.5)\n release('knife')\n return\n } else message('knife_miss', 1)\n }\n if (P.grabPushes >= numbers.grabPushes) {\n crowd?.stun(i, numbers.grabPushStun, -Math.sin(viewYaw) * numbers.grabPushSpeed, -Math.cos(viewYaw) * numbers.grabPushSpeed)\n release('push')\n message('pushed_off', 1.2)\n return\n }\n if (P.grabTimer <= 0) {\n if (P.grabDrown) {\n P.health -= numbers.drownDamage\n P.hurtFlash = numbers.drownFlash\n message('drowning', 2)\n if (P.health <= 0) {\n die('drowned')\n return\n }\n P.grabTimer = numbers.grabSeconds\n P.grabPushes = 0\n return\n }\n if (P.grabNoJaw) {\n hurt(numbers.noJawDamage)\n message('no_jaw', 2)\n } else bite()\n crowd?.chase(i, numbers.grabAttackCooldown)\n release(P.grabNoJaw ? 'scratch' : 'bite')\n }\n return\n }\n // knocked down\n if (P.downTimer > 0) {\n P.downTimer -= dt\n P.vx = P.vz = 0\n if (P.downTimer <= 0) message('stood_up', 0.8)\n return\n }\n if (world.busy?.(dt)) return\n // vaulting a low wall\n if (P.vaultTimer > 0 && P.vault) {\n P.vaultTimer -= dt\n const k = 1 - P.vaultTimer / numbers.vaultSeconds\n P.x = lerp(P.vault[0], P.vault[2], k)\n P.z = lerp(P.vault[1], P.vault[3], k)\n P.y = Math.sin(k * Math.PI) * numbers.vaultHeight\n if (P.vaultTimer <= 0) {\n P.y = 0\n noise(P.x, P.z, numbers.vaultNoise)\n sound('step', numbers.vaultLandVolume)\n }\n return\n }\n if (wasPressed('vault') && P.stamina > numbers.vaultCost && (world.canVault?.() ?? !P.floor)) {\n const fx0 = -Math.sin(viewYaw)\n const fz0 = -Math.cos(viewYaw)\n for (let a = numbers.vaultScanFrom; a <= numbers.vaultScanTo; a += numbers.vaultScanStep) {\n const c = cellKind(P.x + fx0 * a, P.z + fz0 * a)\n if (c === 2) {\n for (let e = a + numbers.vaultLandFrom; e <= a + numbers.vaultLandTo; e += numbers.vaultScanStep) {\n const ex = P.x + fx0 * e\n const ez = P.z + fz0 * e\n if (!solidAt(ex, ez, numbers.vaultCheckHeight) && !solidAt(ex + fx0 * numbers.vaultClearance, ez + fz0 * numbers.vaultClearance, numbers.vaultCheckHeight)) {\n P.vault = [P.x, P.z, ex, ez]\n P.vaultTimer = numbers.vaultSeconds\n P.stamina -= numbers.vaultCost\n sound('step', numbers.vaultStartVolume)\n emit('vault', { from: [P.x, P.z], to: [ex, ez] })\n return\n }\n }\n break\n }\n if (c > 0 && c !== 3) break\n }\n }\n // movement\n const f = input.forward ?? 0\n const s = input.right ?? 0\n if (wasPressed('crouch')) P.crouch = !P.crouch\n const want = f || s\n P.running = !!(input.run && want && P.stamina > numbers.runMinStamina && !input.aim && !P.crouch)\n const fever = P.infected && infection !== null && P.infectionTime > infection.feverSeconds\n let sp = P.running ? derived.runSpeed : P.crouch ? numbers.crouchSpeed : derived.walkSpeed * numbers.walkFactor\n if (fever) sp *= infection!.feverSpeed\n if (input.aim) sp = Math.min(sp, numbers.aimSpeedCap)\n const wet = inWater(P.x, P.z)\n if (wet) sp *= numbers.waterSpeed\n if (P.running) P.stamina = Math.max(0, P.stamina - numbers.runDrain * dt)\n else P.stamina = Math.min(derived.maxStamina, P.stamina + (want ? numbers.regenMoving : numbers.regenStill) * dt)\n const fx = -Math.sin(viewYaw)\n const fz = -Math.cos(viewYaw)\n const mx = fx * f - fz * s\n const mz = fz * f + fx * s\n const ml = Math.hypot(mx, mz) || 1\n const tvx = want ? (mx / ml) * sp : 0\n const tvz = want ? (mz / ml) * sp : 0\n P.vx = lerp(P.vx, tvx, Math.min(1, dt * numbers.acceleration))\n P.vz = lerp(P.vz, tvz, Math.min(1, dt * numbers.acceleration))\n const r = numbers.radius\n const nx = P.x + P.vx * dt\n const nz = P.z + P.vz * dt\n if (!blocked(nx + Math.sign(P.vx) * r, P.z)) P.x = nx\n if (!blocked(P.x, nz + Math.sign(P.vz) * r)) P.z = nz\n world.afterMove?.(P)\n // the player does not walk through the crowd: agents pressed against the body push it out\n if (crowd) {\n const n = crowd.count()\n const rr = numbers.pushApartRadius\n for (let i = 0; i < n; i++) {\n if (!crowd.active(i) || Math.abs(crowd.y(i) - P.y) > numbers.pushApartHeight) continue\n const ex = P.x - crowd.x(i)\n const ez = P.z - crowd.z(i)\n const e2 = ex * ex + ez * ez\n if (e2 < rr * rr && e2 > 1e-5) {\n const e = Math.sqrt(e2)\n const k = ((rr - e) / e) * 0.5\n if (!solidAt(P.x + ex * k, P.z + ez * k, numbers.blockHeight)) {\n P.x += ex * k\n P.z += ez * k\n }\n }\n }\n }\n const spd = Math.hypot(P.vx, P.vz)\n // the legs follow the move even with the torso on the aim; walking backwards flips the stride\n {\n const cy = Math.cos(P.yaw)\n const sy = Math.sin(P.yaw)\n const lx = P.vx * cy - P.vz * sy\n const lz = P.vx * sy + P.vz * cy\n const back = lz < numbers.backwardsBelow ? -1 : 1\n const hip = spd > numbers.hipMinSpeed ? clamp(Math.atan2(lx * back, lz * back), -numbers.hipLimit, numbers.hipLimit) : 0\n P.hip = P.hip + (hip - P.hip) * Math.min(1, dt * numbers.hipFollow)\n P.phase += dt * (spd < numbers.cadenceMinSpeed ? 0 : numbers.cadenceBase + numbers.cadencePerSpeed * spd) * back\n }\n // the body follows the view (fast, no snap); aiming or firing, at once\n {\n const target = viewYaw + Math.PI\n let dy = target - P.yaw\n dy -= Math.round(dy / TAU_APPROX) * TAU_APPROX\n P.yaw += input.aim || input.firing ? dy : dy * Math.min(1, dt * numbers.turnFollow)\n }\n // footsteps make noise: walk 3 m, run 8 m, crouched 1 m (x the sheet's footstep noise, x2 in water)\n P.stepTimer -= dt * spd\n if (P.stepTimer <= 0 && spd > numbers.stepMinSpeed) {\n P.stepTimer = numbers.stepEvery\n noise(P.x, P.z, (P.running ? numbers.stepNoiseRun : P.crouch ? numbers.stepNoiseCrouch : numbers.stepNoiseWalk) * derived.footstepNoise * (wet ? numbers.stepNoiseWater : 1))\n sound('step', P.running ? numbers.stepVolumeRun : numbers.stepVolumeWalk)\n emit('step', { x: P.x, z: P.z, yaw: P.yaw })\n }\n // shove and melee\n if (wasPressed('push') && P.stamina > numbers.shoveCost) {\n P.stamina -= numbers.shoveCost\n shove(viewYaw)\n }\n if (wasPressed('throw')) emit('throw', {})\n if (wasPressed('knife') && P.stamina > numbers.meleeMinStamina) {\n const item = input.melee ?? fist\n P.stamina -= (item.kg ?? 0) > numbers.meleeHeavyKg ? numbers.meleeCostHeavy : numbers.meleeCostLight\n melee(item, viewYaw)\n }\n // panic: chasing agents in sight nearby\n let near = 0\n if (crowd) {\n const n = crowd.count()\n for (let i = 0; i < n; i++) if (crowd.active(i) && crowd.chasing(i)) near += crowd.panicWeight?.(i) ?? 1\n }\n P.panic = clamp(P.panic + (near * numbers.panicGain - (near ? 0 : numbers.panicDecay)) * dt, 0, numbers.panicMax)\n }\n\n return {\n get state() {\n return P\n },\n attributes,\n derived,\n numbers,\n infection,\n update,\n hurt: (amount) => hurt(amount),\n bite: () => bite(),\n grab,\n release: () => release('free'),\n knock(seconds) {\n if (!P.alive) return\n P.downTimer = Math.max(P.downTimer, seconds)\n P.crouch = false\n },\n infect,\n die,\n stage() {\n if (!P.infected || !infection) return 'none'\n return P.infectionTime > infection.deliriumSeconds ? 'delirium' : P.infectionTime > infection.feverSeconds ? 'fever' : 'malaise'\n },\n timeLeft: () => (P.infected && infection ? Math.max(0, infection.deathSeconds - P.infectionTime) : null),\n spreadFactor() {\n const panic = P.panic > derived.composure * numbers.panicSpreadAt ? numbers.panicSpread : 1\n const fever = P.infected && infection && P.infectionTime > infection.feverSeconds ? infection.feverSpread : 1\n return panic * fever * (1 + Math.hypot(P.vx, P.vz) * numbers.moveSpread)\n },\n front,\n on(event, listener) {\n let set = listeners.get(event)\n if (!set) listeners.set(event, (set = new Set()))\n set.add(listener as (event: never) => void)\n return () => void set.delete(listener as (event: never) => void)\n },\n save: () => ({ state: structuredClone(P), attributes }),\n load(save) {\n P = structuredClone(save.state)\n },\n setWorld(next) {\n defaultWorld = next\n },\n }\n}\n","/**\n * Pushing furniture on foot: hold the interaction button against a piece, a timer that grows with its mass fills, and the player then walks with it.\n * Engine-agnostic: the host says where the player wants to go and answers whether the volume of the piece can go there; this says how fast, and when it locks.\n */\n\nexport type FurniturePushPhase = 'idle' | 'grip' | 'push' | 'strain'\nexport type FurniturePushBlock = 'too_heavy' | 'obstacle' | null\n\n/** Every number of the push; a game overrides what it wants (`createFurniturePush(rules)`). */\nexport interface FurniturePushRules {\n /** The most the player's legs put on the floor, newtons: with the friction it says the heaviest thing that moves. */\n readonly forceN: number\n readonly gravity: number\n /** Static friction of a base on a floor, by the material of the piece. */\n readonly frictionByMaterial: Readonly<Record<string, number>>\n readonly defaultFriction: number\n /** The hold before the push: `base + perKg * mass`, at most `max` seconds. */\n readonly gripSeconds: { readonly base: number; readonly perKg: number; readonly max: number }\n /** Metres per second: `max` with nothing on the hands, `min` at the limit of the force. */\n readonly speed: { readonly max: number; readonly min: number }\n /** A press shorter than this is not a push (the host keeps it for a tap, such as grabbing). */\n readonly tapSeconds: number\n /** How long the effort stays after the last step that was refused, so that it does not flicker. */\n readonly strainHoldSeconds: number\n}\n\nexport const FURNITURE_PUSH_DEFAULTS: FurniturePushRules = {\n forceN: 500,\n gravity: 9.81,\n frictionByMaterial: { wood_soft: 0.4, wood_hard: 0.4, mdf: 0.4, plywood: 0.4, steel: 0.35, aluminium: 0.35, cast_iron: 0.4, copper: 0.35, plastic: 0.35, rubber: 0.8, fabric: 0.45, foam: 0.5, ceramic: 0.5, glass: 0.3, tempered_glass: 0.3, brick: 0.6, concrete: 0.65 },\n defaultFriction: 0.45,\n gripSeconds: { base: 0.4, perKg: 0.015, max: 2.5 },\n speed: { max: 1.8, min: 0.35 },\n tapSeconds: 0.2,\n strainHoldSeconds: 0.25,\n}\n\nexport type FurniturePushTarget = { readonly massKg: number; readonly material?: string }\n\nconst frictionOf = (target: FurniturePushTarget, rules: FurniturePushRules): number => (target.material !== undefined ? rules.frictionByMaterial[target.material] : undefined) ?? rules.defaultFriction\n\nconst loadShare = (target: FurniturePushTarget, rules: FurniturePushRules): number => (frictionOf(target, rules) * target.massKg * rules.gravity) / rules.forceN\n\nexport const gripSecondsFor = (massKg: number, rules: FurniturePushRules = FURNITURE_PUSH_DEFAULTS): number => Math.min(rules.gripSeconds.max, rules.gripSeconds.base + rules.gripSeconds.perKg * Math.max(0, massKg))\n\n/** Whether the legs overcome the friction of the piece on the floor. */\nexport const canPush = (target: FurniturePushTarget, rules: FurniturePushRules = FURNITURE_PUSH_DEFAULTS): boolean => loadShare(target, rules) <= 1\n\n/** Metres per second with the piece on the hands: slower the closer it is to the limit of the force, 0 past it. */\nexport const pushSpeedFor = (target: FurniturePushTarget, rules: FurniturePushRules = FURNITURE_PUSH_DEFAULTS): number => {\n const share = loadShare(target, rules)\n return share > 1 ? 0 : rules.speed.max + (rules.speed.min - rules.speed.max) * share\n}\n\nexport type FurniturePushInput = {\n /** Where the player wants to go on the floor: a unit vector, or `[0, 0]` standing. */\n readonly walk: readonly [number, number]\n /** Whether the volume of the piece (and the player behind it) can move by this offset. */\n readonly isFree: (dx: number, dz: number) => boolean\n}\n\nexport type FurniturePushStep = {\n readonly dx: number\n readonly dz: number\n /** The grip closed on this update. */\n readonly engaged: boolean\n /** A step was refused now and the one before was not: the moment the piece hits something. */\n readonly hitObstacle: boolean\n}\n\nexport interface FurniturePush {\n readonly phase: FurniturePushPhase\n /** How far the hold timer is, 0 to 1. */\n readonly progress: number\n readonly block: FurniturePushBlock\n readonly heldSeconds: number\n /** Whether the hold is still short enough to be a tap. */\n readonly isTap: boolean\n begin(target: FurniturePushTarget): void\n release(): void\n update(dt: number, input: FurniturePushInput): FurniturePushStep\n}\n\nconst STILL: FurniturePushStep = { dx: 0, dz: 0, engaged: false, hitObstacle: false }\n\nexport function createFurniturePush(overrides: Partial<FurniturePushRules> = {}): FurniturePush {\n const rules: FurniturePushRules = { ...FURNITURE_PUSH_DEFAULTS, ...overrides }\n let phase: FurniturePushPhase = 'idle'\n let target: FurniturePushTarget = { massKg: 0 }\n let held = 0\n let gripSeconds = 1\n let speed = 0\n let block: FurniturePushBlock = null\n let refused = 0\n let wasRefused = false\n\n const walkWith = (dt: number, input: FurniturePushInput): FurniturePushStep => {\n refused = Math.max(0, refused - dt)\n if (block === 'too_heavy') return STILL\n const [x, z] = input.walk\n if ((x === 0 && z === 0) || dt <= 0) {\n if (refused === 0) {\n phase = 'push'\n block = null\n wasRefused = false\n }\n return STILL\n }\n const dx = x * speed * dt\n const dz = z * speed * dt\n if (input.isFree(dx, dz)) {\n if (refused === 0) {\n phase = 'push'\n block = null\n }\n wasRefused = false\n return { dx, dz, engaged: false, hitObstacle: false }\n }\n const hitObstacle = !wasRefused\n wasRefused = true\n refused = rules.strainHoldSeconds\n phase = 'strain'\n block = 'obstacle'\n return { dx: 0, dz: 0, engaged: false, hitObstacle }\n }\n\n return {\n get phase() {\n return phase\n },\n get progress() {\n return phase === 'idle' ? 0 : Math.min(1, held / gripSeconds)\n },\n get block() {\n return block\n },\n get heldSeconds() {\n return held\n },\n get isTap() {\n return phase === 'grip' && held < rules.tapSeconds\n },\n begin(next) {\n target = next\n phase = 'grip'\n held = 0\n block = null\n refused = 0\n wasRefused = false\n gripSeconds = gripSecondsFor(next.massKg, rules)\n speed = pushSpeedFor(next, rules)\n },\n release() {\n phase = 'idle'\n held = 0\n block = null\n },\n update(dt, input) {\n if (phase === 'idle') return STILL\n held += dt\n if (phase !== 'grip') return walkWith(dt, input)\n if (held < gripSeconds) return STILL\n if (canPush(target, rules)) phase = 'push'\n else {\n phase = 'strain'\n block = 'too_heavy'\n }\n return { ...STILL, engaged: true }\n },\n }\n}\n","import type { KnownDeathCause, PlayerMessageId } from '../types'\n\nexport type PlayerText = Readonly<Record<PlayerMessageId | KnownDeathCause, string>>\n\n/** The game's own words (G 68434, 68452, 68518, 68525-68541, 68547) and the death causes it shows (G 68448, 68454, 68510, 68519, 68539). */\nconst PT_BR: PlayerText = {\n grabbed: 'AGARRADO! Aperte E várias vezes para empurrar ou F para a faca',\n grabbed_drown: 'O AFOGADO TE PUXA PARA O FUNDO! E várias vezes ou F para a faca',\n bitten: 'Você foi mordido. Não há cura.',\n bandaged: 'Curativo feito',\n knife_head: 'Faca na cabeça!',\n knife_miss: 'Errou a facada',\n pushed_off: 'Empurrou!',\n drowning: 'Afogando! Solte-se!',\n no_jaw: 'Sem mandíbula: só arranhou',\n stood_up: 'De pé!',\n infected: 'Morreu infectado',\n killed: 'Morto pela horda',\n bitten_to_death: 'Mordido',\n infection: 'A infecção venceu',\n bled_out: 'Sangrou até a morte',\n hunger_thirst: 'Fome e sede',\n drowned: 'Afogado',\n burned: 'Queimado',\n}\n\nconst EN: PlayerText = {\n grabbed: 'GRABBED! Press E repeatedly to push or F for the knife',\n grabbed_drown: 'THE DROWNED PULLS YOU UNDER! E repeatedly or F for the knife',\n bitten: 'You were bitten. There is no cure.',\n bandaged: 'Wound dressed',\n knife_head: 'Knife to the head!',\n knife_miss: 'The stab missed',\n pushed_off: 'Pushed off!',\n drowning: 'Drowning! Break free!',\n no_jaw: 'No jaw: only a scratch',\n stood_up: 'Back on your feet!',\n infected: 'Died infected',\n killed: 'Killed by the horde',\n bitten_to_death: 'Bitten',\n infection: 'The infection won',\n bled_out: 'Bled to death',\n hunger_thirst: 'Hunger and thirst',\n drowned: 'Drowned',\n burned: 'Burned',\n}\n\nexport const PLAYER_TEXT: Readonly<Record<'en' | 'pt-BR', PlayerText>> = { en: EN, 'pt-BR': PT_BR }\n\n/** The text of a message or death cause id in a locale (`pt-BR` or `en`, the language part is enough); unknown ids come back as they are. */\nexport const playerTextOf = (id: string, locale = 'pt-BR'): string => {\n const table = locale.toLowerCase().startsWith('en') ? EN : PT_BR\n return (table as Readonly<Record<string, string>>)[id] ?? id\n}\n","export type PlayerBenchText = {\n readonly group: string\n readonly name: string\n readonly controls: Readonly<Record<'infection' | 'agility' | 'vigor' | 'seed' | 'hurt' | 'bite' | 'grab' | 'push' | 'knife' | 'bandage' | 'knock' | 'crouch' | 'reset', string>>\n readonly hints: Readonly<Record<'infection' | 'agility' | 'vigor' | 'seed' | 'grab' | 'push', string>>\n readonly metrics: Readonly<Record<'health' | 'stamina' | 'bleeding' | 'wounds' | 'stage' | 'time_left' | 'panic' | 'spread' | 'grab' | 'noise' | 'steps' | 'message', string>>\n readonly stages: Readonly<Record<'none' | 'malaise' | 'fever' | 'delirium' | 'dead', string>>\n readonly scenarios: Readonly<Record<'stamina' | 'bleed_bandage' | 'normal_world' | 'infection_kills' | 'grab_break_free' | 'determinism', string>>\n readonly yes: string\n readonly no: string\n}\n\nconst EN: PlayerBenchText = {\n group: 'Player',\n name: 'Player area',\n controls: {\n infection: 'Individual infection',\n agility: 'Agility',\n vigor: 'Vigor',\n seed: 'Seed',\n hurt: 'Take a hit (10)',\n bite: 'Bite',\n grab: 'Get grabbed',\n push: 'Push (E)',\n knife: 'Knife (F)',\n bandage: 'Bandage (B)',\n knock: 'Knocked down 1.5 s',\n crouch: 'Crouch (C)',\n reset: 'Start again',\n },\n hints: {\n infection: 'Off: a normal world, wounds never infect. On: the game rule (scratch 6%, laceration 22%, bite 100%; fever at 30 s, death at 120 s).',\n agility: 'The sheet: stamina, run speed and footstep noise come from it.',\n vigor: 'The sheet: health, stamina and composure come from it.',\n seed: 'The same seed gives the same wounds and the same knife rolls.',\n grab: 'Something grabs you from behind: 3 s to push it off (6 pushes) or to land the knife (70%).',\n push: 'Shoves what is in front, or pushes off what holds you.',\n },\n metrics: {\n health: 'Health',\n stamina: 'Stamina',\n bleeding: 'Bleeding',\n wounds: 'Wounds',\n stage: 'Infection',\n time_left: 'Time left',\n panic: 'Panic',\n spread: 'Aim spread x',\n grab: 'Grab timer',\n noise: 'Last noise',\n steps: 'Footsteps',\n message: 'Message',\n },\n stages: { none: 'None', malaise: 'Malaise', fever: 'Fever', delirium: 'Delirium', dead: 'Dead' },\n scenarios: {\n stamina: 'Running drains stamina and resting gives it back',\n bleed_bandage: 'A laceration bleeds until it is dressed',\n normal_world: 'In a normal world a bite hurts and bleeds but never infects',\n infection_kills: 'With the infection on, a bite brings fever and kills at its time',\n grab_break_free: 'Six pushes break a grab before the bite',\n determinism: 'The same seed gives the same wounds',\n },\n yes: 'yes',\n no: 'no',\n}\n\nconst PT_BR: PlayerBenchText = {\n group: 'Jogador',\n name: 'Área do jogador',\n controls: {\n infection: 'Infecção individual',\n agility: 'Agilidade',\n vigor: 'Vigor',\n seed: 'Semente',\n hurt: 'Levar um golpe (10)',\n bite: 'Mordida',\n grab: 'Ser agarrado',\n push: 'Empurrar (E)',\n knife: 'Faca (F)',\n bandage: 'Curativo (B)',\n knock: 'Derrubado 1,5 s',\n crouch: 'Agachar (C)',\n reset: 'Recomeçar',\n },\n hints: {\n infection: 'Desligada: mundo normal, ferida nunca infecta. Ligada: a regra do jogo (arranhão 6%, laceração 22%, mordida 100%; febre aos 30 s, morte aos 120 s).',\n agility: 'A ficha: fôlego, velocidade de corrida e ruído dos passos saem dela.',\n vigor: 'A ficha: vida, fôlego e compostura saem dela.',\n seed: 'A mesma semente dá as mesmas feridas e os mesmos golpes de faca.',\n grab: 'Algo te agarra por trás: 3 s para empurrar (6 empurrões) ou acertar a faca (70%).',\n push: 'Empurra o que está na frente, ou se solta do que te segura.',\n },\n metrics: {\n health: 'Vida',\n stamina: 'Fôlego',\n bleeding: 'Sangrando',\n wounds: 'Feridas',\n stage: 'Infecção',\n time_left: 'Tempo restante',\n panic: 'Pânico',\n spread: 'Dispersão x',\n grab: 'Agarrão',\n noise: 'Último ruído',\n steps: 'Passos',\n message: 'Mensagem',\n },\n stages: { none: 'Nenhuma', malaise: 'Mal-estar', fever: 'Febre', delirium: 'Delírio', dead: 'Morto' },\n scenarios: {\n stamina: 'Correr gasta fôlego e descansar devolve',\n bleed_bandage: 'Uma laceração sangra até o curativo',\n normal_world: 'No mundo normal a mordida machuca e sangra, mas não infecta',\n infection_kills: 'Com a infecção ligada, a mordida dá febre e mata no tempo dela',\n grab_break_free: 'Seis empurrões soltam o agarrão antes da mordida',\n determinism: 'A mesma semente dá as mesmas feridas',\n },\n yes: 'sim',\n no: 'não',\n}\n\nexport const playerBenchTextOf = (locale: string): PlayerBenchText => (locale.toLowerCase().startsWith('en') ? EN : PT_BR)\n","import type { BenchChange, ModuleControl, ModuleHost, ModuleMetric, ModuleScenario, TestableModule } from '@adatechnology/game-contracts'\n\nimport { playerTextOf } from '../locales'\nimport { createPlayer } from '../player'\nimport type { Player, PlayerOptions } from '../player'\nimport type { PlayerAction, PlayerCrowd, PlayerInput } from '../types'\nimport { playerBenchTextOf } from './locale'\n\nexport type PlayerTestModuleOptions = PlayerOptions & { readonly locale?: string }\n\n/** What the scenarios use of the context the test room passes. */\nexport interface PlayerScenarioLike {\n expect(condition: boolean, label: string, data?: Record<string, unknown>): void\n}\n\nexport type PlayerTestModule = TestableModule<PlayerScenarioLike> & {\n /** The player in use (replaced when the bench changes the sheet, the seed or the infection). */\n readonly player: Player\n}\n\ntype CameraLike = { position: { x: number; y: number; z: number }; rotation?: { y: number }; getWorldDirection?(target: unknown): { x: number; z: number } }\ntype ThreeLike = { Vector3?: new () => { x: number; y: number; z: number } }\n\nconst MOVING_SPEED = 0.2\nconst SPRINT_SPEED = 3.4\nconst FRAME = 1 / 30\n\n/**\n * One agent standing behind the player for the grab test: the bench has no crowd, so this is the hand that holds. It follows `hold`, takes\n * the shove and the knife, and leaves the count once it lets go.\n */\nconst createGrabber = () => {\n const agent = { x: 0, z: 0, on: false, stunned: 0, hits: 0 }\n const crowd: PlayerCrowd = {\n count: () => (agent.on ? 1 : 0),\n active: () => agent.on,\n x: () => agent.x,\n z: () => agent.z,\n y: () => 0,\n floor: () => 0,\n chasing: () => agent.on,\n down: () => agent.stunned > 0,\n hold(_i, x, z, k) {\n agent.x += (x - agent.x) * k\n agent.z += (z - agent.z) * k\n },\n stun(_i, seconds) {\n agent.stunned = seconds\n agent.on = false\n },\n chase() {\n agent.on = false\n },\n damage() {\n agent.hits += 1\n agent.on = false\n },\n }\n return { agent, crowd }\n}\n\n/**\n * The player area of a test room, against the generic contracts only. The room's camera is the player: where it walks, the player walks; its speed\n * decides walking or running, so stamina, footsteps and their noise follow the viewer. The bench hurts, bites, grabs and knocks the player down,\n * switches the individual infection (off by default: a normal world) and sets the sheet. Footsteps and flesh sounds go to `host.audio`.\n */\nexport function createPlayerTestModule(options: PlayerTestModuleOptions = {}): PlayerTestModule {\n const locale = options.locale ?? 'pt-BR'\n const text = playerBenchTextOf(locale)\n const { locale: _locale, ...playerOptions } = options\n void _locale\n const settings = { infection: options.infection === undefined ? false : options.infection !== false, agility: options.attributes?.agility ?? 5, vigor: options.attributes?.vigor ?? 5, seed: options.seed ?? 1 }\n let host: ModuleHost | null = null\n const grabber = createGrabber()\n let lastNoise = 0\n let steps = 0\n let lastMessage = ''\n let pending: Partial<Record<PlayerAction, boolean>> = {}\n let bandage = false\n let last: { x: number; z: number } | null = null\n const offs: (() => void)[] = []\n\n const build = (): Player => {\n for (const off of offs.splice(0)) off()\n const made = createPlayer({ ...playerOptions, seed: settings.seed, infection: settings.infection, attributes: { ...playerOptions.attributes, agility: settings.agility, vigor: settings.vigor } })\n offs.push(made.on('noise', (e) => void (lastNoise = e.radius)))\n offs.push(made.on('step', () => void (steps += 1)))\n offs.push(made.on('message', (e) => void (lastMessage = playerTextOf(e.id, locale))))\n offs.push(made.on('sound', (e) => void host?.audio?.play({ sound: e.sound, volume: e.volume, position: e.position })))\n offs.push(made.on('died', (e) => host?.log(`player died: ${e.cause}`, { cause: e.cause })))\n lastNoise = 0\n steps = 0\n lastMessage = ''\n return made\n }\n let player = build()\n\n const view = (): { x: number; z: number; yaw: number } | null => {\n const camera = host?.camera as CameraLike | undefined\n if (!camera?.position) return null\n const Vector3 = (host?.THREE as ThreeLike | undefined)?.Vector3\n if (camera.getWorldDirection && Vector3) {\n const look = camera.getWorldDirection(new Vector3())\n return { x: camera.position.x, z: camera.position.z, yaw: Math.atan2(-look.x, -look.z) }\n }\n return { x: camera.position.x, z: camera.position.z, yaw: camera.rotation?.y ?? 0 }\n }\n\n const frame = (dt: number): void => {\n const here = view()\n const speed = here && last && dt > 0 ? Math.hypot(here.x - last.x, here.z - last.z) / dt : 0\n if (here) {\n player.state.x = here.x\n player.state.z = here.z\n }\n const input: PlayerInput = { forward: speed > MOVING_SPEED ? 1 : 0, run: speed > SPRINT_SPEED, yaw: here?.yaw ?? 0, bandage, pressed: pending }\n pending = {}\n bandage = false\n player.update(dt, input, { crowd: grabber.crowd })\n if (here) {\n player.state.x = here.x\n player.state.z = here.z\n last = { x: here.x, z: here.z }\n }\n if (grabber.agent.stunned > 0) grabber.agent.stunned = Math.max(0, grabber.agent.stunned - dt)\n }\n\n const grab = (): void => {\n const P = player.state\n grabber.agent.on = true\n grabber.agent.x = P.x - Math.sin(P.yaw) * player.numbers.grabOffset\n grabber.agent.z = P.z - Math.cos(P.yaw) * player.numbers.grabOffset\n player.grab(0)\n }\n\n const onChange = (change: BenchChange): void => {\n if (change.kind === 'action') {\n const id = change.id\n if (id === 'hurt') player.hurt(10)\n else if (id === 'bite') player.bite()\n else if (id === 'grab') grab()\n else if (id === 'knock') player.knock(1.5)\n else if (id === 'bandage') bandage = true\n else if (id === 'push' || id === 'knife' || id === 'crouch') pending = { ...pending, [id]: true }\n else if (id === 'reset') player = build()\n return\n }\n if (change.kind !== 'control') return\n const { id, value } = change\n if (id === 'infection' && typeof value === 'boolean' && value !== settings.infection) settings.infection = value\n else if ((id === 'agility' || id === 'vigor' || id === 'seed') && typeof value === 'number' && value !== settings[id]) settings[id] = value\n else return\n player = build()\n }\n\n const controls = (): ModuleControl[] => [\n { kind: 'boolean', id: 'infection', name: text.controls.infection, hint: text.hints.infection, default: settings.infection },\n { kind: 'number', id: 'agility', name: text.controls.agility, hint: text.hints.agility, min: 1, max: 8, step: 1, default: settings.agility },\n { kind: 'number', id: 'vigor', name: text.controls.vigor, hint: text.hints.vigor, min: 1, max: 8, step: 1, default: settings.vigor },\n { kind: 'number', id: 'seed', name: text.controls.seed, hint: text.hints.seed, min: 1, max: 9999, step: 1, default: settings.seed },\n { kind: 'action', id: 'hurt', name: text.controls.hurt },\n { kind: 'action', id: 'bite', name: text.controls.bite },\n { kind: 'action', id: 'grab', name: text.controls.grab, hint: text.hints.grab },\n { kind: 'action', id: 'push', name: text.controls.push, hint: text.hints.push },\n { kind: 'action', id: 'knife', name: text.controls.knife },\n { kind: 'action', id: 'bandage', name: text.controls.bandage },\n { kind: 'action', id: 'knock', name: text.controls.knock },\n { kind: 'action', id: 'crouch', name: text.controls.crouch },\n { kind: 'action', id: 'reset', name: text.controls.reset },\n ]\n\n const stageName = (): string => (player.state.alive ? text.stages[player.stage()] : text.stages.dead)\n const metrics = (): ModuleMetric[] => [\n { id: 'health', name: text.metrics.health, digits: 1, max: player.derived.maxHealth, read: () => Math.max(0, player.state.health) },\n { id: 'stamina', name: text.metrics.stamina, digits: 1, max: player.derived.maxStamina, read: () => player.state.stamina },\n { id: 'bleeding', name: text.metrics.bleeding, read: () => (player.state.bleeding ? text.yes : text.no) },\n { id: 'wounds', name: text.metrics.wounds, digits: 0, read: () => player.state.wounds.length },\n { id: 'stage', name: text.metrics.stage, read: stageName },\n { id: 'time_left', name: text.metrics.time_left, unit: 's', digits: 0, read: () => player.timeLeft() ?? 0 },\n { id: 'panic', name: text.metrics.panic, digits: 1, read: () => player.state.panic },\n { id: 'spread', name: text.metrics.spread, digits: 2, read: () => player.spreadFactor() },\n { id: 'grab_timer', name: text.metrics.grab, unit: 's', digits: 1, read: () => (player.state.grabbedBy >= 0 ? player.state.grabTimer : 0) },\n { id: 'noise', name: text.metrics.noise, unit: 'm', digits: 1, read: () => lastNoise },\n { id: 'steps', name: text.metrics.steps, digits: 0, read: () => steps },\n { id: 'message', name: text.metrics.message, read: () => lastMessage },\n ]\n\n // each scenario runs its own player, so the bench's live one is not touched\n const fresh = (extra: PlayerOptions = {}): Player => createPlayer({ ...playerOptions, ...extra })\n const run = (made: Player, seconds: number, input: PlayerInput = {}, crowd?: PlayerCrowd): void => {\n for (let t = 0; t < seconds; t += FRAME) made.update(FRAME, input, crowd ? { crowd } : undefined)\n }\n const scenarios = (): Array<ModuleScenario<PlayerScenarioLike>> => [\n {\n id: 'player_stamina',\n name: text.scenarios.stamina,\n run: ({ expect }) => {\n const made = fresh({ seed: 1 })\n const full = made.state.stamina\n run(made, 4, { forward: 1, run: true })\n const tired = made.state.stamina\n expect(tired < full - 40, 'four seconds of running spend 48 of stamina', { full, tired })\n run(made, 3)\n expect(made.state.stamina > tired, 'standing still gives it back', { tired, rested: made.state.stamina })\n },\n },\n {\n id: 'player_bleed_bandage',\n name: text.scenarios.bleed_bandage,\n run: ({ expect }) => {\n const made = fresh({ seed: 1 })\n made.bite()\n const after = made.state.health\n run(made, 2)\n expect(made.state.bleeding === 1 && made.state.health < after, 'the wound bleeds', { health: made.state.health })\n run(made, FRAME, { bandage: true })\n const dressed = made.state.health\n run(made, 2)\n expect(made.state.bleeding === 0 && made.state.health === dressed, 'dressed, it stops', { health: made.state.health })\n },\n },\n {\n id: 'player_normal_world',\n name: text.scenarios.normal_world,\n run: ({ expect }) => {\n const made = fresh({ seed: 1, infection: false })\n made.bite()\n run(made, 10)\n expect(!made.state.infected && made.state.health < made.derived.maxHealth, 'bitten, hurt, not infected', { health: made.state.health })\n },\n },\n {\n id: 'player_infection_kills',\n name: text.scenarios.infection_kills,\n run: ({ expect }) => {\n const made = fresh({ seed: 1, infection: true })\n made.bite()\n run(made, FRAME, { bandage: true })\n run(made, 40)\n expect(made.stage() === 'fever', 'fever after 30 s', { stage: made.stage() })\n run(made, 90)\n expect(!made.state.alive && made.state.cause === 'infection', 'dead at 120 s', { cause: made.state.cause })\n },\n },\n {\n id: 'player_grab_break_free',\n name: text.scenarios.grab_break_free,\n run: ({ expect }) => {\n const made = fresh({ seed: 1 })\n const { agent, crowd } = createGrabber()\n agent.on = true\n made.grab(0)\n for (let push = 0; push < 6; push++) {\n made.update(FRAME, { pressed: { push: true } }, { crowd })\n made.update(FRAME, {}, { crowd })\n }\n expect(made.state.grabbedBy === -1 && made.state.wounds.length === 0, 'free, and no bite', { grabbedBy: made.state.grabbedBy })\n },\n },\n {\n id: 'player_determinism',\n name: text.scenarios.determinism,\n run: ({ expect }) => {\n const wounds = (seed: number): string => {\n const made = fresh({ seed })\n for (let k = 0; k < 12; k++) made.hurt(1)\n return made.state.wounds.join(',')\n }\n expect(wounds(4) === wounds(4), 'the same seed gives the same wounds')\n expect(wounds(4) !== wounds(5), 'another seed gives others')\n },\n },\n ]\n\n const module: PlayerTestModule = {\n id: 'player_area',\n name: text.name,\n ground: { surface: 'dirt' },\n group: text.group,\n get player() {\n return player\n },\n items: () => [],\n controls: () => controls(),\n metrics: () => metrics(),\n scenarios: () => scenarios(),\n attach(lent) {\n host = lent\n last = null\n const off = lent.bench?.onChange(onChange)\n const offFrame = lent.onFrame(frame)\n return () => {\n off?.()\n offFrame()\n host = null\n }\n },\n }\n return module\n}\n"],"mappings":"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","names":["EN","PT_BR","id"]}
package/dist/index.js CHANGED
@@ -602,6 +602,111 @@ function createPlayer(options = {}) {
602
602
  };
603
603
  }
604
604
 
605
+ // src/furniture-push.ts
606
+ var FURNITURE_PUSH_DEFAULTS = {
607
+ forceN: 500,
608
+ gravity: 9.81,
609
+ frictionByMaterial: { wood_soft: 0.4, wood_hard: 0.4, mdf: 0.4, plywood: 0.4, steel: 0.35, aluminium: 0.35, cast_iron: 0.4, copper: 0.35, plastic: 0.35, rubber: 0.8, fabric: 0.45, foam: 0.5, ceramic: 0.5, glass: 0.3, tempered_glass: 0.3, brick: 0.6, concrete: 0.65 },
610
+ defaultFriction: 0.45,
611
+ gripSeconds: { base: 0.4, perKg: 0.015, max: 2.5 },
612
+ speed: { max: 1.8, min: 0.35 },
613
+ tapSeconds: 0.2,
614
+ strainHoldSeconds: 0.25
615
+ };
616
+ var frictionOf = (target, rules) => (target.material !== void 0 ? rules.frictionByMaterial[target.material] : void 0) ?? rules.defaultFriction;
617
+ var loadShare = (target, rules) => frictionOf(target, rules) * target.massKg * rules.gravity / rules.forceN;
618
+ var gripSecondsFor = (massKg, rules = FURNITURE_PUSH_DEFAULTS) => Math.min(rules.gripSeconds.max, rules.gripSeconds.base + rules.gripSeconds.perKg * Math.max(0, massKg));
619
+ var canPush = (target, rules = FURNITURE_PUSH_DEFAULTS) => loadShare(target, rules) <= 1;
620
+ var pushSpeedFor = (target, rules = FURNITURE_PUSH_DEFAULTS) => {
621
+ const share = loadShare(target, rules);
622
+ return share > 1 ? 0 : rules.speed.max + (rules.speed.min - rules.speed.max) * share;
623
+ };
624
+ var STILL = { dx: 0, dz: 0, engaged: false, hitObstacle: false };
625
+ function createFurniturePush(overrides = {}) {
626
+ const rules = { ...FURNITURE_PUSH_DEFAULTS, ...overrides };
627
+ let phase = "idle";
628
+ let target = { massKg: 0 };
629
+ let held = 0;
630
+ let gripSeconds = 1;
631
+ let speed = 0;
632
+ let block = null;
633
+ let refused = 0;
634
+ let wasRefused = false;
635
+ const walkWith = (dt, input) => {
636
+ refused = Math.max(0, refused - dt);
637
+ if (block === "too_heavy") return STILL;
638
+ const [x, z] = input.walk;
639
+ if (x === 0 && z === 0 || dt <= 0) {
640
+ if (refused === 0) {
641
+ phase = "push";
642
+ block = null;
643
+ wasRefused = false;
644
+ }
645
+ return STILL;
646
+ }
647
+ const dx = x * speed * dt;
648
+ const dz = z * speed * dt;
649
+ if (input.isFree(dx, dz)) {
650
+ if (refused === 0) {
651
+ phase = "push";
652
+ block = null;
653
+ }
654
+ wasRefused = false;
655
+ return { dx, dz, engaged: false, hitObstacle: false };
656
+ }
657
+ const hitObstacle = !wasRefused;
658
+ wasRefused = true;
659
+ refused = rules.strainHoldSeconds;
660
+ phase = "strain";
661
+ block = "obstacle";
662
+ return { dx: 0, dz: 0, engaged: false, hitObstacle };
663
+ };
664
+ return {
665
+ get phase() {
666
+ return phase;
667
+ },
668
+ get progress() {
669
+ return phase === "idle" ? 0 : Math.min(1, held / gripSeconds);
670
+ },
671
+ get block() {
672
+ return block;
673
+ },
674
+ get heldSeconds() {
675
+ return held;
676
+ },
677
+ get isTap() {
678
+ return phase === "grip" && held < rules.tapSeconds;
679
+ },
680
+ begin(next) {
681
+ target = next;
682
+ phase = "grip";
683
+ held = 0;
684
+ block = null;
685
+ refused = 0;
686
+ wasRefused = false;
687
+ gripSeconds = gripSecondsFor(next.massKg, rules);
688
+ speed = pushSpeedFor(next, rules);
689
+ },
690
+ release() {
691
+ phase = "idle";
692
+ held = 0;
693
+ block = null;
694
+ },
695
+ update(dt, input) {
696
+ if (phase === "idle") return STILL;
697
+ held += dt;
698
+ if (phase !== "grip") return walkWith(dt, input);
699
+ if (held < gripSeconds) return STILL;
700
+ if (canPush(target, rules)) phase = "push";
701
+ else {
702
+ phase = "strain";
703
+ block = "too_heavy";
704
+ }
705
+ return { ...STILL, engaged: true };
706
+ }
707
+ };
708
+ }
709
+
605
710
  // src/locales/index.ts
606
711
  var PT_BR = {
607
712
  grabbed: "AGARRADO! Aperte E v\xE1rias vezes para empurrar ou F para a faca",
@@ -990,6 +1095,7 @@ function createPlayerTestModule(options = {}) {
990
1095
  const module = {
991
1096
  id: "player_area",
992
1097
  name: text.name,
1098
+ ground: { surface: "dirt" },
993
1099
  group: text.group,
994
1100
  get player() {
995
1101
  return player;
@@ -1013,13 +1119,18 @@ function createPlayerTestModule(options = {}) {
1013
1119
  return module;
1014
1120
  }
1015
1121
  export {
1122
+ FURNITURE_PUSH_DEFAULTS,
1016
1123
  PLAYER_DEFAULTS,
1017
1124
  PLAYER_TEXT,
1125
+ canPush,
1126
+ createFurniturePush,
1018
1127
  createPlayer,
1019
1128
  createPlayerTestModule,
1020
1129
  createRng,
1021
1130
  deriveVitals,
1022
1131
  drawWound,
1023
- playerTextOf
1132
+ gripSecondsFor,
1133
+ playerTextOf,
1134
+ pushSpeedFor
1024
1135
  };
1025
1136
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/data/defaults.json","../src/rng.ts","../src/player.ts","../src/locales/index.ts","../src/bench/locale.ts","../src/bench/module.ts"],"sourcesContent":["{\n \"sources\": {\n \"game\": \"specs/001-migracao-entregas-dos-times/artefatos/2UG1Mhe9LqJkQKKVsJkTWR/jogo.js\",\n \"attributes\": \"G 62004 FICHA (Personagens 3.2: every attribute 5, no traits)\",\n \"derived\": \"G 62005-62012 DERIV\",\n \"wounds\": \"G 62016 FERIDA (Personagens 3.7): share of each wound kind, and its infection chance (used only when an infection rule is on)\",\n \"infection\": \"G 62015 INFEC (the slice's accelerated clock: fever 30 s, delirium 70 s, death 120 s, reanimation 8 s after); G 68509 fever noise\",\n \"numbers\": \"G 68427-68640 player, playerUpdate, frontZombies, shove, knife; G 68678-68681 the aim spread modifiers; G 65507 walkCad\"\n },\n \"attributes\": { \"strength\": 5, \"vigor\": 5, \"agility\": 5, \"perception\": 5, \"intellect\": 5, \"presence\": 5 },\n \"derived\": {\n \"maxHealth\": { \"base\": 70, \"terms\": [[\"vigor\", 6]] },\n \"maxStamina\": { \"base\": 40, \"terms\": [[\"vigor\", 6], [\"agility\", 4]] },\n \"runSpeed\": { \"base\": 5.2, \"terms\": [[\"agility\", 0.12]] },\n \"walkSpeed\": { \"base\": 1.6, \"terms\": [] },\n \"footstepNoise\": { \"base\": 100, \"terms\": [[\"agility\", -4]], \"divide\": 100 },\n \"composure\": { \"base\": 20, \"terms\": [[\"vigor\", 3], [\"presence\", 4]] }\n },\n \"wounds\": {\n \"scratch\": { \"share\": 0.6, \"infectionChance\": 0.06, \"bleeds\": false },\n \"laceration\": { \"share\": 0.3, \"infectionChance\": 0.22, \"bleeds\": true },\n \"bite\": { \"share\": 0.1, \"infectionChance\": 1, \"bleeds\": true }\n },\n \"infection\": {\n \"feverSeconds\": 30,\n \"deliriumSeconds\": 70,\n \"deathSeconds\": 120,\n \"reanimateSeconds\": 8,\n \"feverNoiseEvery\": 2,\n \"feverNoiseChance\": 0.5,\n \"feverNoiseRadius\": 10,\n \"feverNoiseVolume\": 2,\n \"feverSpeed\": 0.85,\n \"feverSpread\": 1.5\n },\n \"numbers\": {\n \"hurtFlash\": 0.4,\n \"hurtVolume\": 0.8,\n \"biteDamage\": 25,\n \"biteFlash\": 0.8,\n \"biteVolume\": 1.2,\n \"burnPerSecond\": 3,\n \"bleedPerSecond\": 0.15,\n \"grabSeconds\": 3,\n \"grabVolume\": 1,\n \"grabFollow\": 12,\n \"grabOffset\": 0.55,\n \"grabPushCost\": 6,\n \"grabPushMinStamina\": 5,\n \"grabPushVolume\": 1.5,\n \"grabPushes\": 6,\n \"grabPushStun\": 1.2,\n \"grabPushSpeed\": 3,\n \"grabKnifeChance\": 0.7,\n \"grabKnifeRegion\": 0,\n \"grabKnifeDamage\": 22,\n \"grabKnifeDistance\": 0.5,\n \"grabKnifeCut\": 0.7,\n \"drownDamage\": 30,\n \"drownFlash\": 0.8,\n \"noJawDamage\": 8,\n \"grabAttackCooldown\": 2,\n \"vaultSeconds\": 0.7,\n \"vaultCost\": 15,\n \"vaultHeight\": 1.9,\n \"vaultScanFrom\": 0.3,\n \"vaultScanTo\": 1.0,\n \"vaultScanStep\": 0.1,\n \"vaultLandFrom\": 0.4,\n \"vaultLandTo\": 1.4,\n \"vaultClearance\": 0.3,\n \"vaultCheckHeight\": 0.4,\n \"vaultNoise\": 6,\n \"vaultStartVolume\": 0.8,\n \"vaultLandVolume\": 1,\n \"crouchSpeed\": 1.0,\n \"walkFactor\": 1.35,\n \"aimSpeedCap\": 1.4,\n \"waterSpeed\": 0.55,\n \"runMinStamina\": 1,\n \"runDrain\": 12,\n \"regenMoving\": 4,\n \"regenStill\": 8,\n \"acceleration\": 10,\n \"radius\": 0.3,\n \"blockHeight\": 0.4,\n \"pushApartRadius\": 0.55,\n \"pushApartHeight\": 1.2,\n \"hipFollow\": 10,\n \"hipMinSpeed\": 0.3,\n \"hipLimit\": 0.9,\n \"backwardsBelow\": -0.1,\n \"cadenceBase\": 0.5,\n \"cadencePerSpeed\": 0.3,\n \"cadenceMinSpeed\": 0.05,\n \"turnFollow\": 12,\n \"stepEvery\": 0.75,\n \"stepMinSpeed\": 0.3,\n \"stepNoiseRun\": 8,\n \"stepNoiseWalk\": 3,\n \"stepNoiseCrouch\": 1,\n \"stepNoiseWater\": 2,\n \"stepVolumeRun\": 0.6,\n \"stepVolumeWalk\": 0.3,\n \"shoveCost\": 10,\n \"shoveVolume\": 1.2,\n \"shoveRange\": 1.6,\n \"shoveCone\": 0.3,\n \"shoveStun\": 0.9,\n \"shoveSpeed\": 2.5,\n \"meleeMinStamina\": 5,\n \"meleeCostLight\": 5,\n \"meleeCostHeavy\": 12,\n \"meleeHeavyKg\": 1.5,\n \"meleeVolume\": 0.6,\n \"meleeRangeBase\": 0.9,\n \"meleeCone\": 0.5,\n \"meleeHeadChance\": 0.35,\n \"meleeArmChance\": 0.5,\n \"meleeStrengthPerPoint\": 0.06,\n \"meleeStrengthBase\": 5,\n \"meleeCritToCut\": 60,\n \"panicGain\": 1.2,\n \"panicDecay\": 3,\n \"panicMax\": 100,\n \"panicSpreadAt\": 0.6,\n \"panicSpread\": 1.4,\n \"moveSpread\": 0.4\n },\n \"fist\": { \"damage\": 8, \"crit\": 0, \"reach\": 0.5, \"noise\": 1 }\n}\n","const FNV_OFFSET = 0x811c9dc5\nconst FNV_PRIME = 0x01000193\nconst MIX = 0x9e3779b1\n\n/** Deterministic mulberry32 generator; returns floats in [0, 1). */\nexport function 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/** A seed for the stream called `name`: the same seed gives each name its own sequence, so lightning never shifts the schedule. */\nexport function streamSeed(seed: number, name: string): number {\n let hash = FNV_OFFSET\n for (let index = 0; index < name.length; index++) hash = Math.imul(hash ^ name.charCodeAt(index), FNV_PRIME) >>> 0\n return Math.imul((seed >>> 0) ^ hash, MIX) >>> 0\n}\n\nexport function createStream(seed: number, name: string): () => number {\n return createRng(streamSeed(seed, name))\n}\n\nexport function drawBetween(rng: () => number, range: readonly [min: number, max: number]): number {\n return range[0] + rng() * (range[1] - range[0])\n}\n","import defaults from './data/defaults.json'\nimport { createRng } from './rng'\nimport type {\n Attributes,\n DeathCause,\n Derived,\n DerivedFormulas,\n DerivedId,\n InfectionRule,\n LinearFormula,\n MeleeItem,\n PlayerAction,\n PlayerCrowd,\n PlayerEventMap,\n PlayerEventName,\n PlayerInput,\n PlayerMessageId,\n PlayerNumbers,\n PlayerSave,\n PlayerSoundId,\n PlayerState,\n PlayerWorld,\n WoundTable,\n} from './types'\n\nexport const PLAYER_DEFAULTS = defaults as unknown as {\n readonly sources: Readonly<Record<string, string>>\n readonly attributes: Attributes\n readonly derived: DerivedFormulas\n readonly wounds: WoundTable\n readonly infection: InfectionRule\n readonly numbers: PlayerNumbers\n readonly fist: MeleeItem\n}\n\nexport type PlayerOptions = {\n /** The random stream (the game passes its single stream). Default `createRng(seed)`. */\n readonly random?: () => number\n readonly seed?: number\n /** The sheet: every attribute 5 by default. */\n readonly attributes?: Partial<Attributes>\n readonly derived?: Partial<DerivedFormulas>\n readonly wounds?: WoundTable\n /** An individual infection (`true` uses the defaults; an object patches them). Off by default: the normal world comes first. */\n readonly infection?: boolean | Partial<InfectionRule>\n readonly numbers?: Partial<PlayerNumbers>\n readonly fist?: MeleeItem\n readonly position?: { readonly x?: number; readonly z?: number; readonly yaw?: number }\n readonly world?: PlayerWorld\n}\n\nexport type Player = {\n readonly state: PlayerState\n readonly attributes: Attributes\n readonly derived: Derived\n readonly numbers: PlayerNumbers\n readonly infection: InfectionRule | null\n update(dt: number, input?: PlayerInput, world?: PlayerWorld): void\n /** A hit that opens a wound (drawn from the wound table) and may infect. `by` is the agent that hit, if any. */\n hurt(amount: number, by?: number): void\n /** A bite: damage, bleeding, a bite wound and (with an infection rule) the infection. */\n bite(by?: number): void\n grab(by: number, noJaw?: boolean, drown?: boolean): void\n release(): void\n knock(seconds: number): void\n infect(source: string): void\n /** Kills the player with a cause (the host's deaths: a fall, a fire). */\n die(cause: DeathCause): void\n /** Infection stage: `none`, `malaise`, `fever`, `delirium`. */\n stage(): 'none' | 'malaise' | 'fever' | 'delirium'\n /** Seconds the infection has left, or null. */\n timeLeft(): number | null\n /** What the player's state does to aim spread (panic, fever, moving); the weapon multiplies its own spread by it. */\n spreadFactor(): number\n /** The agents in front (nearest first) within `range` m and a cone of `cosMin`, as `[distance, index]`. */\n front(range: number, cosMin: number, yaw: number, crowd?: PlayerCrowd): [number, number][]\n on<K extends PlayerEventName>(event: K, listener: (event: PlayerEventMap[K]) => void): () => void\n save(): PlayerSave\n load(save: PlayerSave): void\n /** The world `update` uses when it is given none. */\n setWorld(world: PlayerWorld): void\n}\n\nconst TAU_APPROX = 6.2832\n\nconst evaluate = (formula: LinearFormula, attributes: Attributes): number => {\n let value = formula.base\n for (const [attribute, coefficient] of formula.terms) value += coefficient * attributes[attribute]\n return formula.divide === undefined ? value : value / formula.divide\n}\n\n/** The derived values of a sheet (the game's `DERIV`). */\nexport const deriveVitals = (attributes: Attributes, formulas: DerivedFormulas = PLAYER_DEFAULTS.derived): Derived => {\n const out = {} as Record<DerivedId, number>\n for (const id of Object.keys(formulas) as DerivedId[]) out[id] = evaluate(formulas[id], attributes)\n return out\n}\n\n/** Which wound a hit opens: one draw, the kinds in the listed order, the last one takes the rest (the game's `FERIDA` draw). */\nexport const drawWound = (wounds: WoundTable, random: () => number): string => {\n const kinds = Object.keys(wounds)\n const draw = random()\n let acc = 0\n for (let k = 0; k < kinds.length - 1; k++) {\n acc += wounds[kinds[k]!]!.share\n if (draw < acc) return kinds[k]!\n }\n return kinds[kinds.length - 1]!\n}\n\nconst clamp = (v: number, a: number, b: number): number => (v < a ? a : v > b ? b : v)\nconst lerp = (a: number, b: number, t: number): number => a + (b - a) * t\n\nconst freshState = (derived: Derived, position: PlayerOptions['position']): PlayerState => ({\n x: position?.x ?? 0,\n z: position?.z ?? 0,\n y: 0,\n vx: 0,\n vz: 0,\n yaw: position?.yaw ?? 0,\n floor: 0,\n alive: true,\n turned: false,\n health: derived.maxHealth,\n stamina: derived.maxStamina,\n crouch: false,\n running: false,\n stepTimer: 0,\n phase: 0,\n hip: 0,\n grabbedBy: -1,\n grabTimer: 0,\n grabPushes: 0,\n grabNoJaw: false,\n grabDrown: false,\n infected: false,\n infectionTime: 0,\n infectionSource: '',\n wounds: [],\n bleeding: 0,\n blind: 0,\n screamBoost: 0,\n panic: 0,\n hurtFlash: 0,\n deathTime: 0,\n cause: '',\n downTimer: 0,\n burnTimer: 0,\n scentTimer: 0,\n vaultTimer: 0,\n vault: null,\n})\n\n/**\n * The player body: a literal port of the team game's `player` and `playerUpdate` (G 68427-68640) with the world, the crowd and the input as\n * arguments instead of globals. The draws on `random` happen in the game's order (wound kind, infection, the fever cough, the knife when grabbed,\n * the melee region), so a game that passes its own stream keeps its sequence.\n */\nexport function createPlayer(options: PlayerOptions = {}): Player {\n const random = options.random ?? createRng(options.seed ?? 1)\n const attributes: Attributes = { ...PLAYER_DEFAULTS.attributes, ...options.attributes }\n const formulas: DerivedFormulas = { ...PLAYER_DEFAULTS.derived, ...options.derived }\n const derived = deriveVitals(attributes, formulas)\n const numbers: PlayerNumbers = { ...PLAYER_DEFAULTS.numbers, ...options.numbers }\n const wounds = options.wounds ?? PLAYER_DEFAULTS.wounds\n const infection: InfectionRule | null =\n options.infection === undefined || options.infection === false ? null : options.infection === true ? PLAYER_DEFAULTS.infection : { ...PLAYER_DEFAULTS.infection, ...options.infection }\n const fist = options.fist ?? PLAYER_DEFAULTS.fist\n const listeners = new Map<PlayerEventName, Set<(event: never) => void>>()\n let P = freshState(derived, options.position)\n let defaultWorld: PlayerWorld = options.world ?? {}\n let world: PlayerWorld = defaultWorld\n\n const emit = <K extends PlayerEventName>(event: K, payload: PlayerEventMap[K]): void => {\n const set = listeners.get(event)\n if (set) for (const listener of set) (listener as (event: PlayerEventMap[K]) => void)(payload)\n }\n const sound = (id: PlayerSoundId, volume: number): void => emit('sound', { sound: id, volume, position: [P.x, P.y, P.z] })\n const noise = (x: number, z: number, radius: number): void => emit('noise', { x, z, radius })\n const message = (id: PlayerMessageId | DeathCause, seconds: number): void => emit('message', { id, seconds })\n const inWater = (x: number, z: number): boolean => world.inWater?.(x, z) ?? false\n const solidAt = (x: number, z: number, y: number): boolean => world.solidAt?.(x, z, y) ?? false\n const cellKind = (x: number, z: number): number => world.cellKind?.(x, z) ?? 0\n const blocked = (x: number, z: number): boolean => (world.blocked ? world.blocked(x, z) : solidAt(x, z, numbers.blockHeight))\n const chanceOf = (kind: string): number => infection?.chances?.[kind] ?? wounds[kind]?.infectionChance ?? 0\n\n const die = (cause: DeathCause): void => {\n if (!P.alive) return\n P.alive = false\n P.cause = cause\n P.deathTime = 0\n P.grabbedBy = -1\n message(cause, 6)\n emit('died', { cause })\n }\n const infect = (source: string): void => {\n if (P.infected || !infection) return\n P.infected = true\n P.infectionTime = 0\n P.infectionSource = source\n emit('infected', { source })\n }\n const release = (how: PlayerEventMap['released']['how'] = 'free'): void => {\n const by = P.grabbedBy\n P.grabbedBy = -1\n if (by >= 0) emit('released', { by, how })\n }\n const hurt = (amount: number): void => {\n if (!P.alive) return\n P.health -= amount\n P.hurtFlash = numbers.hurtFlash\n sound('flesh', numbers.hurtVolume)\n const kind = drawWound(wounds, random)\n P.wounds.push(kind)\n if (wounds[kind]?.bleeds) P.bleeding = 1\n emit('hurt', { amount, wound: kind })\n if (infection && !P.infected && random() < chanceOf(kind)) infect(kind)\n if (P.health <= 0) die(P.infected ? 'infected' : 'killed')\n }\n const bite = (): void => {\n P.health -= numbers.biteDamage\n P.hurtFlash = numbers.biteFlash\n P.bleeding = 1\n P.wounds.push('bite')\n sound('flesh', numbers.biteVolume)\n emit('hurt', { amount: numbers.biteDamage, wound: 'bite' })\n infect('bite')\n message('bitten', 5)\n if (P.health <= 0) die('bitten_to_death')\n }\n const grab = (by: number, noJaw = false, drown = false): void => {\n P.grabbedBy = by\n P.grabTimer = numbers.grabSeconds\n P.grabPushes = 0\n P.grabNoJaw = noJaw\n P.grabDrown = drown\n message(drown ? 'grabbed_drown' : 'grabbed', 3)\n sound('flesh', numbers.grabVolume)\n emit('grabbed', { by, noJaw, drown })\n }\n\n const front = (range: number, cosMin: number, yaw: number, crowd: PlayerCrowd | undefined = world.crowd): [number, number][] => {\n const out: [number, number][] = []\n if (!crowd) return out\n const fx = -Math.sin(yaw)\n const fz = -Math.cos(yaw)\n const n = crowd.count()\n for (let i = 0; i < n; i++) {\n if (!crowd.active(i) || crowd.floor(i) !== P.floor) continue\n const ex = crowd.x(i) - P.x\n const ez = crowd.z(i) - P.z\n const d = Math.hypot(ex, ez)\n if (d < range && (ex * fx + ez * fz) / (d || 1) > cosMin) out.push([d, i])\n }\n return out.sort((a, b) => a[0] - b[0])\n }\n\n const shove = (yaw: number): void => {\n sound('step', numbers.shoveVolume)\n const crowd = world.crowd\n const targets: number[] = []\n for (const [d, i] of front(numbers.shoveRange, numbers.shoveCone, yaw)) {\n crowd!.stun(i, numbers.shoveStun, ((crowd!.x(i) - P.x) / d) * numbers.shoveSpeed, ((crowd!.z(i) - P.z) / d) * numbers.shoveSpeed)\n targets.push(i)\n }\n emit('shove', { targets })\n }\n\n const melee = (item: MeleeItem, yaw: number): void => {\n const t = front(numbers.meleeRangeBase + (item.reach ?? 0), numbers.meleeCone, yaw)[0]\n sound('flesh', numbers.meleeVolume)\n noise(P.x, P.z, item.noise || 1)\n if (!t) return\n const crowd = world.crowd!\n const i = t[1]\n // a blow to the head is x3 in melee; on the ground or crawling it is an execution\n const region = crowd.down(i) ? 0 : random() < numbers.meleeHeadChance ? 0 : random() < numbers.meleeArmChance ? 1 : 2 + Math.floor(random() * 2)\n const damage = item.damage * (1 + (attributes.strength - numbers.meleeStrengthBase) * numbers.meleeStrengthPerPoint)\n const cut = Math.min(1, (item.crit || 0) / numbers.meleeCritToCut)\n crowd.damage(i, { region, amount: damage, distance: t[0], cut })\n emit('melee', { target: i, region, damage, distance: t[0], cut })\n }\n\n const update = (dt: number, input: PlayerInput = {}, frameWorld?: PlayerWorld): void => {\n world = frameWorld ?? defaultWorld\n if (!P.alive) {\n P.deathTime += dt\n if (P.infected && infection && !P.turned && P.deathTime >= infection.reanimateSeconds) {\n P.turned = true\n emit('turned', { x: P.x, z: P.z, floor: P.floor })\n }\n return\n }\n const pressed: Partial<Record<PlayerAction, boolean>> = { ...input.pressed }\n const wasPressed = (action: PlayerAction): boolean => {\n const v = pressed[action] === true\n pressed[action] = false\n return v\n }\n const viewYaw = input.yaw ?? 0\n const crowd = world.crowd\n P.screamBoost = Math.max(0, P.screamBoost - dt)\n P.blind = Math.max(0, P.blind - dt)\n P.hurtFlash = Math.max(0, P.hurtFlash - dt)\n // infection on its own clock\n if (P.infected && infection) {\n const before = P.infectionTime\n P.infectionTime += dt\n if (before <= infection.feverSeconds && P.infectionTime > infection.feverSeconds) emit('stage', { stage: 'fever' })\n if (before <= infection.deliriumSeconds && P.infectionTime > infection.deliriumSeconds) emit('stage', { stage: 'delirium' })\n const every = 1 / infection.feverNoiseEvery\n if (P.infectionTime > infection.feverSeconds && Math.floor(P.infectionTime * every) !== Math.floor((P.infectionTime - dt) * every) && random() < infection.feverNoiseChance) {\n noise(P.x, P.z, infection.feverNoiseRadius)\n sound('step', infection.feverNoiseVolume)\n }\n if (P.infectionTime > infection.deathSeconds) {\n P.health = 0\n die('infection')\n return\n }\n }\n if (P.burnTimer > 0) {\n P.burnTimer -= dt\n P.health -= numbers.burnPerSecond * dt\n if (inWater(P.x, P.z)) P.burnTimer = 0\n }\n P.scentTimer = Math.max(0, P.scentTimer - dt)\n if (P.bleeding) {\n P.health -= dt * numbers.bleedPerSecond\n if (input.bandage && P.bleeding) {\n P.bleeding = 0\n message('bandaged', 2)\n }\n }\n if (P.health <= 0) {\n die(P.infected ? 'infected' : P.bleeding ? 'bled_out' : 'hunger_thirst')\n return\n }\n // grabbed: seconds to react\n if (P.grabbedBy >= 0) {\n const i = P.grabbedBy\n P.grabTimer -= dt\n if (crowd) {\n const k = 1 - Math.exp(-dt * numbers.grabFollow) // glued to the body without a jump\n crowd.hold(i, P.x - Math.sin(P.yaw) * numbers.grabOffset, P.z - Math.cos(P.yaw) * numbers.grabOffset, k, P.x, P.z)\n }\n if (wasPressed('push') && P.stamina > numbers.grabPushMinStamina) {\n P.grabPushes++\n P.stamina -= numbers.grabPushCost\n sound('step', numbers.grabPushVolume)\n }\n if (wasPressed('knife')) {\n if (random() < numbers.grabKnifeChance) {\n crowd?.damage(i, { region: numbers.grabKnifeRegion, amount: numbers.grabKnifeDamage, distance: numbers.grabKnifeDistance, cut: numbers.grabKnifeCut })\n message('knife_head', 1.5)\n release('knife')\n return\n } else message('knife_miss', 1)\n }\n if (P.grabPushes >= numbers.grabPushes) {\n crowd?.stun(i, numbers.grabPushStun, -Math.sin(viewYaw) * numbers.grabPushSpeed, -Math.cos(viewYaw) * numbers.grabPushSpeed)\n release('push')\n message('pushed_off', 1.2)\n return\n }\n if (P.grabTimer <= 0) {\n if (P.grabDrown) {\n P.health -= numbers.drownDamage\n P.hurtFlash = numbers.drownFlash\n message('drowning', 2)\n if (P.health <= 0) {\n die('drowned')\n return\n }\n P.grabTimer = numbers.grabSeconds\n P.grabPushes = 0\n return\n }\n if (P.grabNoJaw) {\n hurt(numbers.noJawDamage)\n message('no_jaw', 2)\n } else bite()\n crowd?.chase(i, numbers.grabAttackCooldown)\n release(P.grabNoJaw ? 'scratch' : 'bite')\n }\n return\n }\n // knocked down\n if (P.downTimer > 0) {\n P.downTimer -= dt\n P.vx = P.vz = 0\n if (P.downTimer <= 0) message('stood_up', 0.8)\n return\n }\n if (world.busy?.(dt)) return\n // vaulting a low wall\n if (P.vaultTimer > 0 && P.vault) {\n P.vaultTimer -= dt\n const k = 1 - P.vaultTimer / numbers.vaultSeconds\n P.x = lerp(P.vault[0], P.vault[2], k)\n P.z = lerp(P.vault[1], P.vault[3], k)\n P.y = Math.sin(k * Math.PI) * numbers.vaultHeight\n if (P.vaultTimer <= 0) {\n P.y = 0\n noise(P.x, P.z, numbers.vaultNoise)\n sound('step', numbers.vaultLandVolume)\n }\n return\n }\n if (wasPressed('vault') && P.stamina > numbers.vaultCost && (world.canVault?.() ?? !P.floor)) {\n const fx0 = -Math.sin(viewYaw)\n const fz0 = -Math.cos(viewYaw)\n for (let a = numbers.vaultScanFrom; a <= numbers.vaultScanTo; a += numbers.vaultScanStep) {\n const c = cellKind(P.x + fx0 * a, P.z + fz0 * a)\n if (c === 2) {\n for (let e = a + numbers.vaultLandFrom; e <= a + numbers.vaultLandTo; e += numbers.vaultScanStep) {\n const ex = P.x + fx0 * e\n const ez = P.z + fz0 * e\n if (!solidAt(ex, ez, numbers.vaultCheckHeight) && !solidAt(ex + fx0 * numbers.vaultClearance, ez + fz0 * numbers.vaultClearance, numbers.vaultCheckHeight)) {\n P.vault = [P.x, P.z, ex, ez]\n P.vaultTimer = numbers.vaultSeconds\n P.stamina -= numbers.vaultCost\n sound('step', numbers.vaultStartVolume)\n emit('vault', { from: [P.x, P.z], to: [ex, ez] })\n return\n }\n }\n break\n }\n if (c > 0 && c !== 3) break\n }\n }\n // movement\n const f = input.forward ?? 0\n const s = input.right ?? 0\n if (wasPressed('crouch')) P.crouch = !P.crouch\n const want = f || s\n P.running = !!(input.run && want && P.stamina > numbers.runMinStamina && !input.aim && !P.crouch)\n const fever = P.infected && infection !== null && P.infectionTime > infection.feverSeconds\n let sp = P.running ? derived.runSpeed : P.crouch ? numbers.crouchSpeed : derived.walkSpeed * numbers.walkFactor\n if (fever) sp *= infection!.feverSpeed\n if (input.aim) sp = Math.min(sp, numbers.aimSpeedCap)\n const wet = inWater(P.x, P.z)\n if (wet) sp *= numbers.waterSpeed\n if (P.running) P.stamina = Math.max(0, P.stamina - numbers.runDrain * dt)\n else P.stamina = Math.min(derived.maxStamina, P.stamina + (want ? numbers.regenMoving : numbers.regenStill) * dt)\n const fx = -Math.sin(viewYaw)\n const fz = -Math.cos(viewYaw)\n const mx = fx * f - fz * s\n const mz = fz * f + fx * s\n const ml = Math.hypot(mx, mz) || 1\n const tvx = want ? (mx / ml) * sp : 0\n const tvz = want ? (mz / ml) * sp : 0\n P.vx = lerp(P.vx, tvx, Math.min(1, dt * numbers.acceleration))\n P.vz = lerp(P.vz, tvz, Math.min(1, dt * numbers.acceleration))\n const r = numbers.radius\n const nx = P.x + P.vx * dt\n const nz = P.z + P.vz * dt\n if (!blocked(nx + Math.sign(P.vx) * r, P.z)) P.x = nx\n if (!blocked(P.x, nz + Math.sign(P.vz) * r)) P.z = nz\n world.afterMove?.(P)\n // the player does not walk through the crowd: agents pressed against the body push it out\n if (crowd) {\n const n = crowd.count()\n const rr = numbers.pushApartRadius\n for (let i = 0; i < n; i++) {\n if (!crowd.active(i) || Math.abs(crowd.y(i) - P.y) > numbers.pushApartHeight) continue\n const ex = P.x - crowd.x(i)\n const ez = P.z - crowd.z(i)\n const e2 = ex * ex + ez * ez\n if (e2 < rr * rr && e2 > 1e-5) {\n const e = Math.sqrt(e2)\n const k = ((rr - e) / e) * 0.5\n if (!solidAt(P.x + ex * k, P.z + ez * k, numbers.blockHeight)) {\n P.x += ex * k\n P.z += ez * k\n }\n }\n }\n }\n const spd = Math.hypot(P.vx, P.vz)\n // the legs follow the move even with the torso on the aim; walking backwards flips the stride\n {\n const cy = Math.cos(P.yaw)\n const sy = Math.sin(P.yaw)\n const lx = P.vx * cy - P.vz * sy\n const lz = P.vx * sy + P.vz * cy\n const back = lz < numbers.backwardsBelow ? -1 : 1\n const hip = spd > numbers.hipMinSpeed ? clamp(Math.atan2(lx * back, lz * back), -numbers.hipLimit, numbers.hipLimit) : 0\n P.hip = P.hip + (hip - P.hip) * Math.min(1, dt * numbers.hipFollow)\n P.phase += dt * (spd < numbers.cadenceMinSpeed ? 0 : numbers.cadenceBase + numbers.cadencePerSpeed * spd) * back\n }\n // the body follows the view (fast, no snap); aiming or firing, at once\n {\n const target = viewYaw + Math.PI\n let dy = target - P.yaw\n dy -= Math.round(dy / TAU_APPROX) * TAU_APPROX\n P.yaw += input.aim || input.firing ? dy : dy * Math.min(1, dt * numbers.turnFollow)\n }\n // footsteps make noise: walk 3 m, run 8 m, crouched 1 m (x the sheet's footstep noise, x2 in water)\n P.stepTimer -= dt * spd\n if (P.stepTimer <= 0 && spd > numbers.stepMinSpeed) {\n P.stepTimer = numbers.stepEvery\n noise(P.x, P.z, (P.running ? numbers.stepNoiseRun : P.crouch ? numbers.stepNoiseCrouch : numbers.stepNoiseWalk) * derived.footstepNoise * (wet ? numbers.stepNoiseWater : 1))\n sound('step', P.running ? numbers.stepVolumeRun : numbers.stepVolumeWalk)\n emit('step', { x: P.x, z: P.z, yaw: P.yaw })\n }\n // shove and melee\n if (wasPressed('push') && P.stamina > numbers.shoveCost) {\n P.stamina -= numbers.shoveCost\n shove(viewYaw)\n }\n if (wasPressed('throw')) emit('throw', {})\n if (wasPressed('knife') && P.stamina > numbers.meleeMinStamina) {\n const item = input.melee ?? fist\n P.stamina -= (item.kg ?? 0) > numbers.meleeHeavyKg ? numbers.meleeCostHeavy : numbers.meleeCostLight\n melee(item, viewYaw)\n }\n // panic: chasing agents in sight nearby\n let near = 0\n if (crowd) {\n const n = crowd.count()\n for (let i = 0; i < n; i++) if (crowd.active(i) && crowd.chasing(i)) near += crowd.panicWeight?.(i) ?? 1\n }\n P.panic = clamp(P.panic + (near * numbers.panicGain - (near ? 0 : numbers.panicDecay)) * dt, 0, numbers.panicMax)\n }\n\n return {\n get state() {\n return P\n },\n attributes,\n derived,\n numbers,\n infection,\n update,\n hurt: (amount) => hurt(amount),\n bite: () => bite(),\n grab,\n release: () => release('free'),\n knock(seconds) {\n if (!P.alive) return\n P.downTimer = Math.max(P.downTimer, seconds)\n P.crouch = false\n },\n infect,\n die,\n stage() {\n if (!P.infected || !infection) return 'none'\n return P.infectionTime > infection.deliriumSeconds ? 'delirium' : P.infectionTime > infection.feverSeconds ? 'fever' : 'malaise'\n },\n timeLeft: () => (P.infected && infection ? Math.max(0, infection.deathSeconds - P.infectionTime) : null),\n spreadFactor() {\n const panic = P.panic > derived.composure * numbers.panicSpreadAt ? numbers.panicSpread : 1\n const fever = P.infected && infection && P.infectionTime > infection.feverSeconds ? infection.feverSpread : 1\n return panic * fever * (1 + Math.hypot(P.vx, P.vz) * numbers.moveSpread)\n },\n front,\n on(event, listener) {\n let set = listeners.get(event)\n if (!set) listeners.set(event, (set = new Set()))\n set.add(listener as (event: never) => void)\n return () => void set.delete(listener as (event: never) => void)\n },\n save: () => ({ state: structuredClone(P), attributes }),\n load(save) {\n P = structuredClone(save.state)\n },\n setWorld(next) {\n defaultWorld = next\n },\n }\n}\n","import type { KnownDeathCause, PlayerMessageId } from '../types'\n\nexport type PlayerText = Readonly<Record<PlayerMessageId | KnownDeathCause, string>>\n\n/** The game's own words (G 68434, 68452, 68518, 68525-68541, 68547) and the death causes it shows (G 68448, 68454, 68510, 68519, 68539). */\nconst PT_BR: PlayerText = {\n grabbed: 'AGARRADO! Aperte E várias vezes para empurrar ou F para a faca',\n grabbed_drown: 'O AFOGADO TE PUXA PARA O FUNDO! E várias vezes ou F para a faca',\n bitten: 'Você foi mordido. Não há cura.',\n bandaged: 'Curativo feito',\n knife_head: 'Faca na cabeça!',\n knife_miss: 'Errou a facada',\n pushed_off: 'Empurrou!',\n drowning: 'Afogando! Solte-se!',\n no_jaw: 'Sem mandíbula: só arranhou',\n stood_up: 'De pé!',\n infected: 'Morreu infectado',\n killed: 'Morto pela horda',\n bitten_to_death: 'Mordido',\n infection: 'A infecção venceu',\n bled_out: 'Sangrou até a morte',\n hunger_thirst: 'Fome e sede',\n drowned: 'Afogado',\n burned: 'Queimado',\n}\n\nconst EN: PlayerText = {\n grabbed: 'GRABBED! Press E repeatedly to push or F for the knife',\n grabbed_drown: 'THE DROWNED PULLS YOU UNDER! E repeatedly or F for the knife',\n bitten: 'You were bitten. There is no cure.',\n bandaged: 'Wound dressed',\n knife_head: 'Knife to the head!',\n knife_miss: 'The stab missed',\n pushed_off: 'Pushed off!',\n drowning: 'Drowning! Break free!',\n no_jaw: 'No jaw: only a scratch',\n stood_up: 'Back on your feet!',\n infected: 'Died infected',\n killed: 'Killed by the horde',\n bitten_to_death: 'Bitten',\n infection: 'The infection won',\n bled_out: 'Bled to death',\n hunger_thirst: 'Hunger and thirst',\n drowned: 'Drowned',\n burned: 'Burned',\n}\n\nexport const PLAYER_TEXT: Readonly<Record<'en' | 'pt-BR', PlayerText>> = { en: EN, 'pt-BR': PT_BR }\n\n/** The text of a message or death cause id in a locale (`pt-BR` or `en`, the language part is enough); unknown ids come back as they are. */\nexport const playerTextOf = (id: string, locale = 'pt-BR'): string => {\n const table = locale.toLowerCase().startsWith('en') ? EN : PT_BR\n return (table as Readonly<Record<string, string>>)[id] ?? id\n}\n","export type PlayerBenchText = {\n readonly group: string\n readonly name: string\n readonly controls: Readonly<Record<'infection' | 'agility' | 'vigor' | 'seed' | 'hurt' | 'bite' | 'grab' | 'push' | 'knife' | 'bandage' | 'knock' | 'crouch' | 'reset', string>>\n readonly hints: Readonly<Record<'infection' | 'agility' | 'vigor' | 'seed' | 'grab' | 'push', string>>\n readonly metrics: Readonly<Record<'health' | 'stamina' | 'bleeding' | 'wounds' | 'stage' | 'time_left' | 'panic' | 'spread' | 'grab' | 'noise' | 'steps' | 'message', string>>\n readonly stages: Readonly<Record<'none' | 'malaise' | 'fever' | 'delirium' | 'dead', string>>\n readonly scenarios: Readonly<Record<'stamina' | 'bleed_bandage' | 'normal_world' | 'infection_kills' | 'grab_break_free' | 'determinism', string>>\n readonly yes: string\n readonly no: string\n}\n\nconst EN: PlayerBenchText = {\n group: 'Player',\n name: 'Player area',\n controls: {\n infection: 'Individual infection',\n agility: 'Agility',\n vigor: 'Vigor',\n seed: 'Seed',\n hurt: 'Take a hit (10)',\n bite: 'Bite',\n grab: 'Get grabbed',\n push: 'Push (E)',\n knife: 'Knife (F)',\n bandage: 'Bandage (B)',\n knock: 'Knocked down 1.5 s',\n crouch: 'Crouch (C)',\n reset: 'Start again',\n },\n hints: {\n infection: 'Off: a normal world, wounds never infect. On: the game rule (scratch 6%, laceration 22%, bite 100%; fever at 30 s, death at 120 s).',\n agility: 'The sheet: stamina, run speed and footstep noise come from it.',\n vigor: 'The sheet: health, stamina and composure come from it.',\n seed: 'The same seed gives the same wounds and the same knife rolls.',\n grab: 'Something grabs you from behind: 3 s to push it off (6 pushes) or to land the knife (70%).',\n push: 'Shoves what is in front, or pushes off what holds you.',\n },\n metrics: {\n health: 'Health',\n stamina: 'Stamina',\n bleeding: 'Bleeding',\n wounds: 'Wounds',\n stage: 'Infection',\n time_left: 'Time left',\n panic: 'Panic',\n spread: 'Aim spread x',\n grab: 'Grab timer',\n noise: 'Last noise',\n steps: 'Footsteps',\n message: 'Message',\n },\n stages: { none: 'None', malaise: 'Malaise', fever: 'Fever', delirium: 'Delirium', dead: 'Dead' },\n scenarios: {\n stamina: 'Running drains stamina and resting gives it back',\n bleed_bandage: 'A laceration bleeds until it is dressed',\n normal_world: 'In a normal world a bite hurts and bleeds but never infects',\n infection_kills: 'With the infection on, a bite brings fever and kills at its time',\n grab_break_free: 'Six pushes break a grab before the bite',\n determinism: 'The same seed gives the same wounds',\n },\n yes: 'yes',\n no: 'no',\n}\n\nconst PT_BR: PlayerBenchText = {\n group: 'Jogador',\n name: 'Área do jogador',\n controls: {\n infection: 'Infecção individual',\n agility: 'Agilidade',\n vigor: 'Vigor',\n seed: 'Semente',\n hurt: 'Levar um golpe (10)',\n bite: 'Mordida',\n grab: 'Ser agarrado',\n push: 'Empurrar (E)',\n knife: 'Faca (F)',\n bandage: 'Curativo (B)',\n knock: 'Derrubado 1,5 s',\n crouch: 'Agachar (C)',\n reset: 'Recomeçar',\n },\n hints: {\n infection: 'Desligada: mundo normal, ferida nunca infecta. Ligada: a regra do jogo (arranhão 6%, laceração 22%, mordida 100%; febre aos 30 s, morte aos 120 s).',\n agility: 'A ficha: fôlego, velocidade de corrida e ruído dos passos saem dela.',\n vigor: 'A ficha: vida, fôlego e compostura saem dela.',\n seed: 'A mesma semente dá as mesmas feridas e os mesmos golpes de faca.',\n grab: 'Algo te agarra por trás: 3 s para empurrar (6 empurrões) ou acertar a faca (70%).',\n push: 'Empurra o que está na frente, ou se solta do que te segura.',\n },\n metrics: {\n health: 'Vida',\n stamina: 'Fôlego',\n bleeding: 'Sangrando',\n wounds: 'Feridas',\n stage: 'Infecção',\n time_left: 'Tempo restante',\n panic: 'Pânico',\n spread: 'Dispersão x',\n grab: 'Agarrão',\n noise: 'Último ruído',\n steps: 'Passos',\n message: 'Mensagem',\n },\n stages: { none: 'Nenhuma', malaise: 'Mal-estar', fever: 'Febre', delirium: 'Delírio', dead: 'Morto' },\n scenarios: {\n stamina: 'Correr gasta fôlego e descansar devolve',\n bleed_bandage: 'Uma laceração sangra até o curativo',\n normal_world: 'No mundo normal a mordida machuca e sangra, mas não infecta',\n infection_kills: 'Com a infecção ligada, a mordida dá febre e mata no tempo dela',\n grab_break_free: 'Seis empurrões soltam o agarrão antes da mordida',\n determinism: 'A mesma semente dá as mesmas feridas',\n },\n yes: 'sim',\n no: 'não',\n}\n\nexport const playerBenchTextOf = (locale: string): PlayerBenchText => (locale.toLowerCase().startsWith('en') ? EN : PT_BR)\n","import type { BenchChange, ModuleControl, ModuleHost, ModuleMetric, ModuleScenario, TestableModule } from '@adatechnology/game-contracts'\n\nimport { playerTextOf } from '../locales'\nimport { createPlayer } from '../player'\nimport type { Player, PlayerOptions } from '../player'\nimport type { PlayerAction, PlayerCrowd, PlayerInput } from '../types'\nimport { playerBenchTextOf } from './locale'\n\nexport type PlayerTestModuleOptions = PlayerOptions & { readonly locale?: string }\n\n/** What the scenarios use of the context the test room passes. */\nexport interface PlayerScenarioLike {\n expect(condition: boolean, label: string, data?: Record<string, unknown>): void\n}\n\nexport type PlayerTestModule = TestableModule<PlayerScenarioLike> & {\n /** The player in use (replaced when the bench changes the sheet, the seed or the infection). */\n readonly player: Player\n}\n\ntype CameraLike = { position: { x: number; y: number; z: number }; rotation?: { y: number }; getWorldDirection?(target: unknown): { x: number; z: number } }\ntype ThreeLike = { Vector3?: new () => { x: number; y: number; z: number } }\n\nconst MOVING_SPEED = 0.2\nconst SPRINT_SPEED = 3.4\nconst FRAME = 1 / 30\n\n/**\n * One agent standing behind the player for the grab test: the bench has no crowd, so this is the hand that holds. It follows `hold`, takes\n * the shove and the knife, and leaves the count once it lets go.\n */\nconst createGrabber = () => {\n const agent = { x: 0, z: 0, on: false, stunned: 0, hits: 0 }\n const crowd: PlayerCrowd = {\n count: () => (agent.on ? 1 : 0),\n active: () => agent.on,\n x: () => agent.x,\n z: () => agent.z,\n y: () => 0,\n floor: () => 0,\n chasing: () => agent.on,\n down: () => agent.stunned > 0,\n hold(_i, x, z, k) {\n agent.x += (x - agent.x) * k\n agent.z += (z - agent.z) * k\n },\n stun(_i, seconds) {\n agent.stunned = seconds\n agent.on = false\n },\n chase() {\n agent.on = false\n },\n damage() {\n agent.hits += 1\n agent.on = false\n },\n }\n return { agent, crowd }\n}\n\n/**\n * The player area of a test room, against the generic contracts only. The room's camera is the player: where it walks, the player walks; its speed\n * decides walking or running, so stamina, footsteps and their noise follow the viewer. The bench hurts, bites, grabs and knocks the player down,\n * switches the individual infection (off by default: a normal world) and sets the sheet. Footsteps and flesh sounds go to `host.audio`.\n */\nexport function createPlayerTestModule(options: PlayerTestModuleOptions = {}): PlayerTestModule {\n const locale = options.locale ?? 'pt-BR'\n const text = playerBenchTextOf(locale)\n const { locale: _locale, ...playerOptions } = options\n void _locale\n const settings = { infection: options.infection === undefined ? false : options.infection !== false, agility: options.attributes?.agility ?? 5, vigor: options.attributes?.vigor ?? 5, seed: options.seed ?? 1 }\n let host: ModuleHost | null = null\n const grabber = createGrabber()\n let lastNoise = 0\n let steps = 0\n let lastMessage = ''\n let pending: Partial<Record<PlayerAction, boolean>> = {}\n let bandage = false\n let last: { x: number; z: number } | null = null\n const offs: (() => void)[] = []\n\n const build = (): Player => {\n for (const off of offs.splice(0)) off()\n const made = createPlayer({ ...playerOptions, seed: settings.seed, infection: settings.infection, attributes: { ...playerOptions.attributes, agility: settings.agility, vigor: settings.vigor } })\n offs.push(made.on('noise', (e) => void (lastNoise = e.radius)))\n offs.push(made.on('step', () => void (steps += 1)))\n offs.push(made.on('message', (e) => void (lastMessage = playerTextOf(e.id, locale))))\n offs.push(made.on('sound', (e) => void host?.audio?.play({ sound: e.sound, volume: e.volume, position: e.position })))\n offs.push(made.on('died', (e) => host?.log(`player died: ${e.cause}`, { cause: e.cause })))\n lastNoise = 0\n steps = 0\n lastMessage = ''\n return made\n }\n let player = build()\n\n const view = (): { x: number; z: number; yaw: number } | null => {\n const camera = host?.camera as CameraLike | undefined\n if (!camera?.position) return null\n const Vector3 = (host?.THREE as ThreeLike | undefined)?.Vector3\n if (camera.getWorldDirection && Vector3) {\n const look = camera.getWorldDirection(new Vector3())\n return { x: camera.position.x, z: camera.position.z, yaw: Math.atan2(-look.x, -look.z) }\n }\n return { x: camera.position.x, z: camera.position.z, yaw: camera.rotation?.y ?? 0 }\n }\n\n const frame = (dt: number): void => {\n const here = view()\n const speed = here && last && dt > 0 ? Math.hypot(here.x - last.x, here.z - last.z) / dt : 0\n if (here) {\n player.state.x = here.x\n player.state.z = here.z\n }\n const input: PlayerInput = { forward: speed > MOVING_SPEED ? 1 : 0, run: speed > SPRINT_SPEED, yaw: here?.yaw ?? 0, bandage, pressed: pending }\n pending = {}\n bandage = false\n player.update(dt, input, { crowd: grabber.crowd })\n if (here) {\n player.state.x = here.x\n player.state.z = here.z\n last = { x: here.x, z: here.z }\n }\n if (grabber.agent.stunned > 0) grabber.agent.stunned = Math.max(0, grabber.agent.stunned - dt)\n }\n\n const grab = (): void => {\n const P = player.state\n grabber.agent.on = true\n grabber.agent.x = P.x - Math.sin(P.yaw) * player.numbers.grabOffset\n grabber.agent.z = P.z - Math.cos(P.yaw) * player.numbers.grabOffset\n player.grab(0)\n }\n\n const onChange = (change: BenchChange): void => {\n if (change.kind === 'action') {\n const id = change.id\n if (id === 'hurt') player.hurt(10)\n else if (id === 'bite') player.bite()\n else if (id === 'grab') grab()\n else if (id === 'knock') player.knock(1.5)\n else if (id === 'bandage') bandage = true\n else if (id === 'push' || id === 'knife' || id === 'crouch') pending = { ...pending, [id]: true }\n else if (id === 'reset') player = build()\n return\n }\n if (change.kind !== 'control') return\n const { id, value } = change\n if (id === 'infection' && typeof value === 'boolean' && value !== settings.infection) settings.infection = value\n else if ((id === 'agility' || id === 'vigor' || id === 'seed') && typeof value === 'number' && value !== settings[id]) settings[id] = value\n else return\n player = build()\n }\n\n const controls = (): ModuleControl[] => [\n { kind: 'boolean', id: 'infection', name: text.controls.infection, hint: text.hints.infection, default: settings.infection },\n { kind: 'number', id: 'agility', name: text.controls.agility, hint: text.hints.agility, min: 1, max: 8, step: 1, default: settings.agility },\n { kind: 'number', id: 'vigor', name: text.controls.vigor, hint: text.hints.vigor, min: 1, max: 8, step: 1, default: settings.vigor },\n { kind: 'number', id: 'seed', name: text.controls.seed, hint: text.hints.seed, min: 1, max: 9999, step: 1, default: settings.seed },\n { kind: 'action', id: 'hurt', name: text.controls.hurt },\n { kind: 'action', id: 'bite', name: text.controls.bite },\n { kind: 'action', id: 'grab', name: text.controls.grab, hint: text.hints.grab },\n { kind: 'action', id: 'push', name: text.controls.push, hint: text.hints.push },\n { kind: 'action', id: 'knife', name: text.controls.knife },\n { kind: 'action', id: 'bandage', name: text.controls.bandage },\n { kind: 'action', id: 'knock', name: text.controls.knock },\n { kind: 'action', id: 'crouch', name: text.controls.crouch },\n { kind: 'action', id: 'reset', name: text.controls.reset },\n ]\n\n const stageName = (): string => (player.state.alive ? text.stages[player.stage()] : text.stages.dead)\n const metrics = (): ModuleMetric[] => [\n { id: 'health', name: text.metrics.health, digits: 1, max: player.derived.maxHealth, read: () => Math.max(0, player.state.health) },\n { id: 'stamina', name: text.metrics.stamina, digits: 1, max: player.derived.maxStamina, read: () => player.state.stamina },\n { id: 'bleeding', name: text.metrics.bleeding, read: () => (player.state.bleeding ? text.yes : text.no) },\n { id: 'wounds', name: text.metrics.wounds, digits: 0, read: () => player.state.wounds.length },\n { id: 'stage', name: text.metrics.stage, read: stageName },\n { id: 'time_left', name: text.metrics.time_left, unit: 's', digits: 0, read: () => player.timeLeft() ?? 0 },\n { id: 'panic', name: text.metrics.panic, digits: 1, read: () => player.state.panic },\n { id: 'spread', name: text.metrics.spread, digits: 2, read: () => player.spreadFactor() },\n { id: 'grab_timer', name: text.metrics.grab, unit: 's', digits: 1, read: () => (player.state.grabbedBy >= 0 ? player.state.grabTimer : 0) },\n { id: 'noise', name: text.metrics.noise, unit: 'm', digits: 1, read: () => lastNoise },\n { id: 'steps', name: text.metrics.steps, digits: 0, read: () => steps },\n { id: 'message', name: text.metrics.message, read: () => lastMessage },\n ]\n\n // each scenario runs its own player, so the bench's live one is not touched\n const fresh = (extra: PlayerOptions = {}): Player => createPlayer({ ...playerOptions, ...extra })\n const run = (made: Player, seconds: number, input: PlayerInput = {}, crowd?: PlayerCrowd): void => {\n for (let t = 0; t < seconds; t += FRAME) made.update(FRAME, input, crowd ? { crowd } : undefined)\n }\n const scenarios = (): Array<ModuleScenario<PlayerScenarioLike>> => [\n {\n id: 'player_stamina',\n name: text.scenarios.stamina,\n run: ({ expect }) => {\n const made = fresh({ seed: 1 })\n const full = made.state.stamina\n run(made, 4, { forward: 1, run: true })\n const tired = made.state.stamina\n expect(tired < full - 40, 'four seconds of running spend 48 of stamina', { full, tired })\n run(made, 3)\n expect(made.state.stamina > tired, 'standing still gives it back', { tired, rested: made.state.stamina })\n },\n },\n {\n id: 'player_bleed_bandage',\n name: text.scenarios.bleed_bandage,\n run: ({ expect }) => {\n const made = fresh({ seed: 1 })\n made.bite()\n const after = made.state.health\n run(made, 2)\n expect(made.state.bleeding === 1 && made.state.health < after, 'the wound bleeds', { health: made.state.health })\n run(made, FRAME, { bandage: true })\n const dressed = made.state.health\n run(made, 2)\n expect(made.state.bleeding === 0 && made.state.health === dressed, 'dressed, it stops', { health: made.state.health })\n },\n },\n {\n id: 'player_normal_world',\n name: text.scenarios.normal_world,\n run: ({ expect }) => {\n const made = fresh({ seed: 1, infection: false })\n made.bite()\n run(made, 10)\n expect(!made.state.infected && made.state.health < made.derived.maxHealth, 'bitten, hurt, not infected', { health: made.state.health })\n },\n },\n {\n id: 'player_infection_kills',\n name: text.scenarios.infection_kills,\n run: ({ expect }) => {\n const made = fresh({ seed: 1, infection: true })\n made.bite()\n run(made, FRAME, { bandage: true })\n run(made, 40)\n expect(made.stage() === 'fever', 'fever after 30 s', { stage: made.stage() })\n run(made, 90)\n expect(!made.state.alive && made.state.cause === 'infection', 'dead at 120 s', { cause: made.state.cause })\n },\n },\n {\n id: 'player_grab_break_free',\n name: text.scenarios.grab_break_free,\n run: ({ expect }) => {\n const made = fresh({ seed: 1 })\n const { agent, crowd } = createGrabber()\n agent.on = true\n made.grab(0)\n for (let push = 0; push < 6; push++) {\n made.update(FRAME, { pressed: { push: true } }, { crowd })\n made.update(FRAME, {}, { crowd })\n }\n expect(made.state.grabbedBy === -1 && made.state.wounds.length === 0, 'free, and no bite', { grabbedBy: made.state.grabbedBy })\n },\n },\n {\n id: 'player_determinism',\n name: text.scenarios.determinism,\n run: ({ expect }) => {\n const wounds = (seed: number): string => {\n const made = fresh({ seed })\n for (let k = 0; k < 12; k++) made.hurt(1)\n return made.state.wounds.join(',')\n }\n expect(wounds(4) === wounds(4), 'the same seed gives the same wounds')\n expect(wounds(4) !== wounds(5), 'another seed gives others')\n },\n },\n ]\n\n const module: PlayerTestModule = {\n id: 'player_area',\n name: text.name,\n group: text.group,\n get player() {\n return player\n },\n items: () => [],\n controls: () => controls(),\n metrics: () => metrics(),\n scenarios: () => scenarios(),\n attach(lent) {\n host = lent\n last = null\n const off = lent.bench?.onChange(onChange)\n const offFrame = lent.onFrame(frame)\n return () => {\n off?.()\n offFrame()\n host = null\n }\n },\n }\n return module\n}\n"],"mappings":"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","names":["EN","PT_BR","id"]}
1
+ {"version":3,"sources":["../src/data/defaults.json","../src/rng.ts","../src/player.ts","../src/furniture-push.ts","../src/locales/index.ts","../src/bench/locale.ts","../src/bench/module.ts"],"sourcesContent":["{\n \"sources\": {\n \"game\": \"specs/001-migracao-entregas-dos-times/artefatos/2UG1Mhe9LqJkQKKVsJkTWR/jogo.js\",\n \"attributes\": \"G 62004 FICHA (Personagens 3.2: every attribute 5, no traits)\",\n \"derived\": \"G 62005-62012 DERIV\",\n \"wounds\": \"G 62016 FERIDA (Personagens 3.7): share of each wound kind, and its infection chance (used only when an infection rule is on)\",\n \"infection\": \"G 62015 INFEC (the slice's accelerated clock: fever 30 s, delirium 70 s, death 120 s, reanimation 8 s after); G 68509 fever noise\",\n \"numbers\": \"G 68427-68640 player, playerUpdate, frontZombies, shove, knife; G 68678-68681 the aim spread modifiers; G 65507 walkCad\"\n },\n \"attributes\": { \"strength\": 5, \"vigor\": 5, \"agility\": 5, \"perception\": 5, \"intellect\": 5, \"presence\": 5 },\n \"derived\": {\n \"maxHealth\": { \"base\": 70, \"terms\": [[\"vigor\", 6]] },\n \"maxStamina\": { \"base\": 40, \"terms\": [[\"vigor\", 6], [\"agility\", 4]] },\n \"runSpeed\": { \"base\": 5.2, \"terms\": [[\"agility\", 0.12]] },\n \"walkSpeed\": { \"base\": 1.6, \"terms\": [] },\n \"footstepNoise\": { \"base\": 100, \"terms\": [[\"agility\", -4]], \"divide\": 100 },\n \"composure\": { \"base\": 20, \"terms\": [[\"vigor\", 3], [\"presence\", 4]] }\n },\n \"wounds\": {\n \"scratch\": { \"share\": 0.6, \"infectionChance\": 0.06, \"bleeds\": false },\n \"laceration\": { \"share\": 0.3, \"infectionChance\": 0.22, \"bleeds\": true },\n \"bite\": { \"share\": 0.1, \"infectionChance\": 1, \"bleeds\": true }\n },\n \"infection\": {\n \"feverSeconds\": 30,\n \"deliriumSeconds\": 70,\n \"deathSeconds\": 120,\n \"reanimateSeconds\": 8,\n \"feverNoiseEvery\": 2,\n \"feverNoiseChance\": 0.5,\n \"feverNoiseRadius\": 10,\n \"feverNoiseVolume\": 2,\n \"feverSpeed\": 0.85,\n \"feverSpread\": 1.5\n },\n \"numbers\": {\n \"hurtFlash\": 0.4,\n \"hurtVolume\": 0.8,\n \"biteDamage\": 25,\n \"biteFlash\": 0.8,\n \"biteVolume\": 1.2,\n \"burnPerSecond\": 3,\n \"bleedPerSecond\": 0.15,\n \"grabSeconds\": 3,\n \"grabVolume\": 1,\n \"grabFollow\": 12,\n \"grabOffset\": 0.55,\n \"grabPushCost\": 6,\n \"grabPushMinStamina\": 5,\n \"grabPushVolume\": 1.5,\n \"grabPushes\": 6,\n \"grabPushStun\": 1.2,\n \"grabPushSpeed\": 3,\n \"grabKnifeChance\": 0.7,\n \"grabKnifeRegion\": 0,\n \"grabKnifeDamage\": 22,\n \"grabKnifeDistance\": 0.5,\n \"grabKnifeCut\": 0.7,\n \"drownDamage\": 30,\n \"drownFlash\": 0.8,\n \"noJawDamage\": 8,\n \"grabAttackCooldown\": 2,\n \"vaultSeconds\": 0.7,\n \"vaultCost\": 15,\n \"vaultHeight\": 1.9,\n \"vaultScanFrom\": 0.3,\n \"vaultScanTo\": 1.0,\n \"vaultScanStep\": 0.1,\n \"vaultLandFrom\": 0.4,\n \"vaultLandTo\": 1.4,\n \"vaultClearance\": 0.3,\n \"vaultCheckHeight\": 0.4,\n \"vaultNoise\": 6,\n \"vaultStartVolume\": 0.8,\n \"vaultLandVolume\": 1,\n \"crouchSpeed\": 1.0,\n \"walkFactor\": 1.35,\n \"aimSpeedCap\": 1.4,\n \"waterSpeed\": 0.55,\n \"runMinStamina\": 1,\n \"runDrain\": 12,\n \"regenMoving\": 4,\n \"regenStill\": 8,\n \"acceleration\": 10,\n \"radius\": 0.3,\n \"blockHeight\": 0.4,\n \"pushApartRadius\": 0.55,\n \"pushApartHeight\": 1.2,\n \"hipFollow\": 10,\n \"hipMinSpeed\": 0.3,\n \"hipLimit\": 0.9,\n \"backwardsBelow\": -0.1,\n \"cadenceBase\": 0.5,\n \"cadencePerSpeed\": 0.3,\n \"cadenceMinSpeed\": 0.05,\n \"turnFollow\": 12,\n \"stepEvery\": 0.75,\n \"stepMinSpeed\": 0.3,\n \"stepNoiseRun\": 8,\n \"stepNoiseWalk\": 3,\n \"stepNoiseCrouch\": 1,\n \"stepNoiseWater\": 2,\n \"stepVolumeRun\": 0.6,\n \"stepVolumeWalk\": 0.3,\n \"shoveCost\": 10,\n \"shoveVolume\": 1.2,\n \"shoveRange\": 1.6,\n \"shoveCone\": 0.3,\n \"shoveStun\": 0.9,\n \"shoveSpeed\": 2.5,\n \"meleeMinStamina\": 5,\n \"meleeCostLight\": 5,\n \"meleeCostHeavy\": 12,\n \"meleeHeavyKg\": 1.5,\n \"meleeVolume\": 0.6,\n \"meleeRangeBase\": 0.9,\n \"meleeCone\": 0.5,\n \"meleeHeadChance\": 0.35,\n \"meleeArmChance\": 0.5,\n \"meleeStrengthPerPoint\": 0.06,\n \"meleeStrengthBase\": 5,\n \"meleeCritToCut\": 60,\n \"panicGain\": 1.2,\n \"panicDecay\": 3,\n \"panicMax\": 100,\n \"panicSpreadAt\": 0.6,\n \"panicSpread\": 1.4,\n \"moveSpread\": 0.4\n },\n \"fist\": { \"damage\": 8, \"crit\": 0, \"reach\": 0.5, \"noise\": 1 }\n}\n","const FNV_OFFSET = 0x811c9dc5\nconst FNV_PRIME = 0x01000193\nconst MIX = 0x9e3779b1\n\n/** Deterministic mulberry32 generator; returns floats in [0, 1). */\nexport function 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/** A seed for the stream called `name`: the same seed gives each name its own sequence, so lightning never shifts the schedule. */\nexport function streamSeed(seed: number, name: string): number {\n let hash = FNV_OFFSET\n for (let index = 0; index < name.length; index++) hash = Math.imul(hash ^ name.charCodeAt(index), FNV_PRIME) >>> 0\n return Math.imul((seed >>> 0) ^ hash, MIX) >>> 0\n}\n\nexport function createStream(seed: number, name: string): () => number {\n return createRng(streamSeed(seed, name))\n}\n\nexport function drawBetween(rng: () => number, range: readonly [min: number, max: number]): number {\n return range[0] + rng() * (range[1] - range[0])\n}\n","import defaults from './data/defaults.json'\nimport { createRng } from './rng'\nimport type {\n Attributes,\n DeathCause,\n Derived,\n DerivedFormulas,\n DerivedId,\n InfectionRule,\n LinearFormula,\n MeleeItem,\n PlayerAction,\n PlayerCrowd,\n PlayerEventMap,\n PlayerEventName,\n PlayerInput,\n PlayerMessageId,\n PlayerNumbers,\n PlayerSave,\n PlayerSoundId,\n PlayerState,\n PlayerWorld,\n WoundTable,\n} from './types'\n\nexport const PLAYER_DEFAULTS = defaults as unknown as {\n readonly sources: Readonly<Record<string, string>>\n readonly attributes: Attributes\n readonly derived: DerivedFormulas\n readonly wounds: WoundTable\n readonly infection: InfectionRule\n readonly numbers: PlayerNumbers\n readonly fist: MeleeItem\n}\n\nexport type PlayerOptions = {\n /** The random stream (the game passes its single stream). Default `createRng(seed)`. */\n readonly random?: () => number\n readonly seed?: number\n /** The sheet: every attribute 5 by default. */\n readonly attributes?: Partial<Attributes>\n readonly derived?: Partial<DerivedFormulas>\n readonly wounds?: WoundTable\n /** An individual infection (`true` uses the defaults; an object patches them). Off by default: the normal world comes first. */\n readonly infection?: boolean | Partial<InfectionRule>\n readonly numbers?: Partial<PlayerNumbers>\n readonly fist?: MeleeItem\n readonly position?: { readonly x?: number; readonly z?: number; readonly yaw?: number }\n readonly world?: PlayerWorld\n}\n\nexport type Player = {\n readonly state: PlayerState\n readonly attributes: Attributes\n readonly derived: Derived\n readonly numbers: PlayerNumbers\n readonly infection: InfectionRule | null\n update(dt: number, input?: PlayerInput, world?: PlayerWorld): void\n /** A hit that opens a wound (drawn from the wound table) and may infect. `by` is the agent that hit, if any. */\n hurt(amount: number, by?: number): void\n /** A bite: damage, bleeding, a bite wound and (with an infection rule) the infection. */\n bite(by?: number): void\n grab(by: number, noJaw?: boolean, drown?: boolean): void\n release(): void\n knock(seconds: number): void\n infect(source: string): void\n /** Kills the player with a cause (the host's deaths: a fall, a fire). */\n die(cause: DeathCause): void\n /** Infection stage: `none`, `malaise`, `fever`, `delirium`. */\n stage(): 'none' | 'malaise' | 'fever' | 'delirium'\n /** Seconds the infection has left, or null. */\n timeLeft(): number | null\n /** What the player's state does to aim spread (panic, fever, moving); the weapon multiplies its own spread by it. */\n spreadFactor(): number\n /** The agents in front (nearest first) within `range` m and a cone of `cosMin`, as `[distance, index]`. */\n front(range: number, cosMin: number, yaw: number, crowd?: PlayerCrowd): [number, number][]\n on<K extends PlayerEventName>(event: K, listener: (event: PlayerEventMap[K]) => void): () => void\n save(): PlayerSave\n load(save: PlayerSave): void\n /** The world `update` uses when it is given none. */\n setWorld(world: PlayerWorld): void\n}\n\nconst TAU_APPROX = 6.2832\n\nconst evaluate = (formula: LinearFormula, attributes: Attributes): number => {\n let value = formula.base\n for (const [attribute, coefficient] of formula.terms) value += coefficient * attributes[attribute]\n return formula.divide === undefined ? value : value / formula.divide\n}\n\n/** The derived values of a sheet (the game's `DERIV`). */\nexport const deriveVitals = (attributes: Attributes, formulas: DerivedFormulas = PLAYER_DEFAULTS.derived): Derived => {\n const out = {} as Record<DerivedId, number>\n for (const id of Object.keys(formulas) as DerivedId[]) out[id] = evaluate(formulas[id], attributes)\n return out\n}\n\n/** Which wound a hit opens: one draw, the kinds in the listed order, the last one takes the rest (the game's `FERIDA` draw). */\nexport const drawWound = (wounds: WoundTable, random: () => number): string => {\n const kinds = Object.keys(wounds)\n const draw = random()\n let acc = 0\n for (let k = 0; k < kinds.length - 1; k++) {\n acc += wounds[kinds[k]!]!.share\n if (draw < acc) return kinds[k]!\n }\n return kinds[kinds.length - 1]!\n}\n\nconst clamp = (v: number, a: number, b: number): number => (v < a ? a : v > b ? b : v)\nconst lerp = (a: number, b: number, t: number): number => a + (b - a) * t\n\nconst freshState = (derived: Derived, position: PlayerOptions['position']): PlayerState => ({\n x: position?.x ?? 0,\n z: position?.z ?? 0,\n y: 0,\n vx: 0,\n vz: 0,\n yaw: position?.yaw ?? 0,\n floor: 0,\n alive: true,\n turned: false,\n health: derived.maxHealth,\n stamina: derived.maxStamina,\n crouch: false,\n running: false,\n stepTimer: 0,\n phase: 0,\n hip: 0,\n grabbedBy: -1,\n grabTimer: 0,\n grabPushes: 0,\n grabNoJaw: false,\n grabDrown: false,\n infected: false,\n infectionTime: 0,\n infectionSource: '',\n wounds: [],\n bleeding: 0,\n blind: 0,\n screamBoost: 0,\n panic: 0,\n hurtFlash: 0,\n deathTime: 0,\n cause: '',\n downTimer: 0,\n burnTimer: 0,\n scentTimer: 0,\n vaultTimer: 0,\n vault: null,\n})\n\n/**\n * The player body: a literal port of the team game's `player` and `playerUpdate` (G 68427-68640) with the world, the crowd and the input as\n * arguments instead of globals. The draws on `random` happen in the game's order (wound kind, infection, the fever cough, the knife when grabbed,\n * the melee region), so a game that passes its own stream keeps its sequence.\n */\nexport function createPlayer(options: PlayerOptions = {}): Player {\n const random = options.random ?? createRng(options.seed ?? 1)\n const attributes: Attributes = { ...PLAYER_DEFAULTS.attributes, ...options.attributes }\n const formulas: DerivedFormulas = { ...PLAYER_DEFAULTS.derived, ...options.derived }\n const derived = deriveVitals(attributes, formulas)\n const numbers: PlayerNumbers = { ...PLAYER_DEFAULTS.numbers, ...options.numbers }\n const wounds = options.wounds ?? PLAYER_DEFAULTS.wounds\n const infection: InfectionRule | null =\n options.infection === undefined || options.infection === false ? null : options.infection === true ? PLAYER_DEFAULTS.infection : { ...PLAYER_DEFAULTS.infection, ...options.infection }\n const fist = options.fist ?? PLAYER_DEFAULTS.fist\n const listeners = new Map<PlayerEventName, Set<(event: never) => void>>()\n let P = freshState(derived, options.position)\n let defaultWorld: PlayerWorld = options.world ?? {}\n let world: PlayerWorld = defaultWorld\n\n const emit = <K extends PlayerEventName>(event: K, payload: PlayerEventMap[K]): void => {\n const set = listeners.get(event)\n if (set) for (const listener of set) (listener as (event: PlayerEventMap[K]) => void)(payload)\n }\n const sound = (id: PlayerSoundId, volume: number): void => emit('sound', { sound: id, volume, position: [P.x, P.y, P.z] })\n const noise = (x: number, z: number, radius: number): void => emit('noise', { x, z, radius })\n const message = (id: PlayerMessageId | DeathCause, seconds: number): void => emit('message', { id, seconds })\n const inWater = (x: number, z: number): boolean => world.inWater?.(x, z) ?? false\n const solidAt = (x: number, z: number, y: number): boolean => world.solidAt?.(x, z, y) ?? false\n const cellKind = (x: number, z: number): number => world.cellKind?.(x, z) ?? 0\n const blocked = (x: number, z: number): boolean => (world.blocked ? world.blocked(x, z) : solidAt(x, z, numbers.blockHeight))\n const chanceOf = (kind: string): number => infection?.chances?.[kind] ?? wounds[kind]?.infectionChance ?? 0\n\n const die = (cause: DeathCause): void => {\n if (!P.alive) return\n P.alive = false\n P.cause = cause\n P.deathTime = 0\n P.grabbedBy = -1\n message(cause, 6)\n emit('died', { cause })\n }\n const infect = (source: string): void => {\n if (P.infected || !infection) return\n P.infected = true\n P.infectionTime = 0\n P.infectionSource = source\n emit('infected', { source })\n }\n const release = (how: PlayerEventMap['released']['how'] = 'free'): void => {\n const by = P.grabbedBy\n P.grabbedBy = -1\n if (by >= 0) emit('released', { by, how })\n }\n const hurt = (amount: number): void => {\n if (!P.alive) return\n P.health -= amount\n P.hurtFlash = numbers.hurtFlash\n sound('flesh', numbers.hurtVolume)\n const kind = drawWound(wounds, random)\n P.wounds.push(kind)\n if (wounds[kind]?.bleeds) P.bleeding = 1\n emit('hurt', { amount, wound: kind })\n if (infection && !P.infected && random() < chanceOf(kind)) infect(kind)\n if (P.health <= 0) die(P.infected ? 'infected' : 'killed')\n }\n const bite = (): void => {\n P.health -= numbers.biteDamage\n P.hurtFlash = numbers.biteFlash\n P.bleeding = 1\n P.wounds.push('bite')\n sound('flesh', numbers.biteVolume)\n emit('hurt', { amount: numbers.biteDamage, wound: 'bite' })\n infect('bite')\n message('bitten', 5)\n if (P.health <= 0) die('bitten_to_death')\n }\n const grab = (by: number, noJaw = false, drown = false): void => {\n P.grabbedBy = by\n P.grabTimer = numbers.grabSeconds\n P.grabPushes = 0\n P.grabNoJaw = noJaw\n P.grabDrown = drown\n message(drown ? 'grabbed_drown' : 'grabbed', 3)\n sound('flesh', numbers.grabVolume)\n emit('grabbed', { by, noJaw, drown })\n }\n\n const front = (range: number, cosMin: number, yaw: number, crowd: PlayerCrowd | undefined = world.crowd): [number, number][] => {\n const out: [number, number][] = []\n if (!crowd) return out\n const fx = -Math.sin(yaw)\n const fz = -Math.cos(yaw)\n const n = crowd.count()\n for (let i = 0; i < n; i++) {\n if (!crowd.active(i) || crowd.floor(i) !== P.floor) continue\n const ex = crowd.x(i) - P.x\n const ez = crowd.z(i) - P.z\n const d = Math.hypot(ex, ez)\n if (d < range && (ex * fx + ez * fz) / (d || 1) > cosMin) out.push([d, i])\n }\n return out.sort((a, b) => a[0] - b[0])\n }\n\n const shove = (yaw: number): void => {\n sound('step', numbers.shoveVolume)\n const crowd = world.crowd\n const targets: number[] = []\n for (const [d, i] of front(numbers.shoveRange, numbers.shoveCone, yaw)) {\n crowd!.stun(i, numbers.shoveStun, ((crowd!.x(i) - P.x) / d) * numbers.shoveSpeed, ((crowd!.z(i) - P.z) / d) * numbers.shoveSpeed)\n targets.push(i)\n }\n emit('shove', { targets })\n }\n\n const melee = (item: MeleeItem, yaw: number): void => {\n const t = front(numbers.meleeRangeBase + (item.reach ?? 0), numbers.meleeCone, yaw)[0]\n sound('flesh', numbers.meleeVolume)\n noise(P.x, P.z, item.noise || 1)\n if (!t) return\n const crowd = world.crowd!\n const i = t[1]\n // a blow to the head is x3 in melee; on the ground or crawling it is an execution\n const region = crowd.down(i) ? 0 : random() < numbers.meleeHeadChance ? 0 : random() < numbers.meleeArmChance ? 1 : 2 + Math.floor(random() * 2)\n const damage = item.damage * (1 + (attributes.strength - numbers.meleeStrengthBase) * numbers.meleeStrengthPerPoint)\n const cut = Math.min(1, (item.crit || 0) / numbers.meleeCritToCut)\n crowd.damage(i, { region, amount: damage, distance: t[0], cut })\n emit('melee', { target: i, region, damage, distance: t[0], cut })\n }\n\n const update = (dt: number, input: PlayerInput = {}, frameWorld?: PlayerWorld): void => {\n world = frameWorld ?? defaultWorld\n if (!P.alive) {\n P.deathTime += dt\n if (P.infected && infection && !P.turned && P.deathTime >= infection.reanimateSeconds) {\n P.turned = true\n emit('turned', { x: P.x, z: P.z, floor: P.floor })\n }\n return\n }\n const pressed: Partial<Record<PlayerAction, boolean>> = { ...input.pressed }\n const wasPressed = (action: PlayerAction): boolean => {\n const v = pressed[action] === true\n pressed[action] = false\n return v\n }\n const viewYaw = input.yaw ?? 0\n const crowd = world.crowd\n P.screamBoost = Math.max(0, P.screamBoost - dt)\n P.blind = Math.max(0, P.blind - dt)\n P.hurtFlash = Math.max(0, P.hurtFlash - dt)\n // infection on its own clock\n if (P.infected && infection) {\n const before = P.infectionTime\n P.infectionTime += dt\n if (before <= infection.feverSeconds && P.infectionTime > infection.feverSeconds) emit('stage', { stage: 'fever' })\n if (before <= infection.deliriumSeconds && P.infectionTime > infection.deliriumSeconds) emit('stage', { stage: 'delirium' })\n const every = 1 / infection.feverNoiseEvery\n if (P.infectionTime > infection.feverSeconds && Math.floor(P.infectionTime * every) !== Math.floor((P.infectionTime - dt) * every) && random() < infection.feverNoiseChance) {\n noise(P.x, P.z, infection.feverNoiseRadius)\n sound('step', infection.feverNoiseVolume)\n }\n if (P.infectionTime > infection.deathSeconds) {\n P.health = 0\n die('infection')\n return\n }\n }\n if (P.burnTimer > 0) {\n P.burnTimer -= dt\n P.health -= numbers.burnPerSecond * dt\n if (inWater(P.x, P.z)) P.burnTimer = 0\n }\n P.scentTimer = Math.max(0, P.scentTimer - dt)\n if (P.bleeding) {\n P.health -= dt * numbers.bleedPerSecond\n if (input.bandage && P.bleeding) {\n P.bleeding = 0\n message('bandaged', 2)\n }\n }\n if (P.health <= 0) {\n die(P.infected ? 'infected' : P.bleeding ? 'bled_out' : 'hunger_thirst')\n return\n }\n // grabbed: seconds to react\n if (P.grabbedBy >= 0) {\n const i = P.grabbedBy\n P.grabTimer -= dt\n if (crowd) {\n const k = 1 - Math.exp(-dt * numbers.grabFollow) // glued to the body without a jump\n crowd.hold(i, P.x - Math.sin(P.yaw) * numbers.grabOffset, P.z - Math.cos(P.yaw) * numbers.grabOffset, k, P.x, P.z)\n }\n if (wasPressed('push') && P.stamina > numbers.grabPushMinStamina) {\n P.grabPushes++\n P.stamina -= numbers.grabPushCost\n sound('step', numbers.grabPushVolume)\n }\n if (wasPressed('knife')) {\n if (random() < numbers.grabKnifeChance) {\n crowd?.damage(i, { region: numbers.grabKnifeRegion, amount: numbers.grabKnifeDamage, distance: numbers.grabKnifeDistance, cut: numbers.grabKnifeCut })\n message('knife_head', 1.5)\n release('knife')\n return\n } else message('knife_miss', 1)\n }\n if (P.grabPushes >= numbers.grabPushes) {\n crowd?.stun(i, numbers.grabPushStun, -Math.sin(viewYaw) * numbers.grabPushSpeed, -Math.cos(viewYaw) * numbers.grabPushSpeed)\n release('push')\n message('pushed_off', 1.2)\n return\n }\n if (P.grabTimer <= 0) {\n if (P.grabDrown) {\n P.health -= numbers.drownDamage\n P.hurtFlash = numbers.drownFlash\n message('drowning', 2)\n if (P.health <= 0) {\n die('drowned')\n return\n }\n P.grabTimer = numbers.grabSeconds\n P.grabPushes = 0\n return\n }\n if (P.grabNoJaw) {\n hurt(numbers.noJawDamage)\n message('no_jaw', 2)\n } else bite()\n crowd?.chase(i, numbers.grabAttackCooldown)\n release(P.grabNoJaw ? 'scratch' : 'bite')\n }\n return\n }\n // knocked down\n if (P.downTimer > 0) {\n P.downTimer -= dt\n P.vx = P.vz = 0\n if (P.downTimer <= 0) message('stood_up', 0.8)\n return\n }\n if (world.busy?.(dt)) return\n // vaulting a low wall\n if (P.vaultTimer > 0 && P.vault) {\n P.vaultTimer -= dt\n const k = 1 - P.vaultTimer / numbers.vaultSeconds\n P.x = lerp(P.vault[0], P.vault[2], k)\n P.z = lerp(P.vault[1], P.vault[3], k)\n P.y = Math.sin(k * Math.PI) * numbers.vaultHeight\n if (P.vaultTimer <= 0) {\n P.y = 0\n noise(P.x, P.z, numbers.vaultNoise)\n sound('step', numbers.vaultLandVolume)\n }\n return\n }\n if (wasPressed('vault') && P.stamina > numbers.vaultCost && (world.canVault?.() ?? !P.floor)) {\n const fx0 = -Math.sin(viewYaw)\n const fz0 = -Math.cos(viewYaw)\n for (let a = numbers.vaultScanFrom; a <= numbers.vaultScanTo; a += numbers.vaultScanStep) {\n const c = cellKind(P.x + fx0 * a, P.z + fz0 * a)\n if (c === 2) {\n for (let e = a + numbers.vaultLandFrom; e <= a + numbers.vaultLandTo; e += numbers.vaultScanStep) {\n const ex = P.x + fx0 * e\n const ez = P.z + fz0 * e\n if (!solidAt(ex, ez, numbers.vaultCheckHeight) && !solidAt(ex + fx0 * numbers.vaultClearance, ez + fz0 * numbers.vaultClearance, numbers.vaultCheckHeight)) {\n P.vault = [P.x, P.z, ex, ez]\n P.vaultTimer = numbers.vaultSeconds\n P.stamina -= numbers.vaultCost\n sound('step', numbers.vaultStartVolume)\n emit('vault', { from: [P.x, P.z], to: [ex, ez] })\n return\n }\n }\n break\n }\n if (c > 0 && c !== 3) break\n }\n }\n // movement\n const f = input.forward ?? 0\n const s = input.right ?? 0\n if (wasPressed('crouch')) P.crouch = !P.crouch\n const want = f || s\n P.running = !!(input.run && want && P.stamina > numbers.runMinStamina && !input.aim && !P.crouch)\n const fever = P.infected && infection !== null && P.infectionTime > infection.feverSeconds\n let sp = P.running ? derived.runSpeed : P.crouch ? numbers.crouchSpeed : derived.walkSpeed * numbers.walkFactor\n if (fever) sp *= infection!.feverSpeed\n if (input.aim) sp = Math.min(sp, numbers.aimSpeedCap)\n const wet = inWater(P.x, P.z)\n if (wet) sp *= numbers.waterSpeed\n if (P.running) P.stamina = Math.max(0, P.stamina - numbers.runDrain * dt)\n else P.stamina = Math.min(derived.maxStamina, P.stamina + (want ? numbers.regenMoving : numbers.regenStill) * dt)\n const fx = -Math.sin(viewYaw)\n const fz = -Math.cos(viewYaw)\n const mx = fx * f - fz * s\n const mz = fz * f + fx * s\n const ml = Math.hypot(mx, mz) || 1\n const tvx = want ? (mx / ml) * sp : 0\n const tvz = want ? (mz / ml) * sp : 0\n P.vx = lerp(P.vx, tvx, Math.min(1, dt * numbers.acceleration))\n P.vz = lerp(P.vz, tvz, Math.min(1, dt * numbers.acceleration))\n const r = numbers.radius\n const nx = P.x + P.vx * dt\n const nz = P.z + P.vz * dt\n if (!blocked(nx + Math.sign(P.vx) * r, P.z)) P.x = nx\n if (!blocked(P.x, nz + Math.sign(P.vz) * r)) P.z = nz\n world.afterMove?.(P)\n // the player does not walk through the crowd: agents pressed against the body push it out\n if (crowd) {\n const n = crowd.count()\n const rr = numbers.pushApartRadius\n for (let i = 0; i < n; i++) {\n if (!crowd.active(i) || Math.abs(crowd.y(i) - P.y) > numbers.pushApartHeight) continue\n const ex = P.x - crowd.x(i)\n const ez = P.z - crowd.z(i)\n const e2 = ex * ex + ez * ez\n if (e2 < rr * rr && e2 > 1e-5) {\n const e = Math.sqrt(e2)\n const k = ((rr - e) / e) * 0.5\n if (!solidAt(P.x + ex * k, P.z + ez * k, numbers.blockHeight)) {\n P.x += ex * k\n P.z += ez * k\n }\n }\n }\n }\n const spd = Math.hypot(P.vx, P.vz)\n // the legs follow the move even with the torso on the aim; walking backwards flips the stride\n {\n const cy = Math.cos(P.yaw)\n const sy = Math.sin(P.yaw)\n const lx = P.vx * cy - P.vz * sy\n const lz = P.vx * sy + P.vz * cy\n const back = lz < numbers.backwardsBelow ? -1 : 1\n const hip = spd > numbers.hipMinSpeed ? clamp(Math.atan2(lx * back, lz * back), -numbers.hipLimit, numbers.hipLimit) : 0\n P.hip = P.hip + (hip - P.hip) * Math.min(1, dt * numbers.hipFollow)\n P.phase += dt * (spd < numbers.cadenceMinSpeed ? 0 : numbers.cadenceBase + numbers.cadencePerSpeed * spd) * back\n }\n // the body follows the view (fast, no snap); aiming or firing, at once\n {\n const target = viewYaw + Math.PI\n let dy = target - P.yaw\n dy -= Math.round(dy / TAU_APPROX) * TAU_APPROX\n P.yaw += input.aim || input.firing ? dy : dy * Math.min(1, dt * numbers.turnFollow)\n }\n // footsteps make noise: walk 3 m, run 8 m, crouched 1 m (x the sheet's footstep noise, x2 in water)\n P.stepTimer -= dt * spd\n if (P.stepTimer <= 0 && spd > numbers.stepMinSpeed) {\n P.stepTimer = numbers.stepEvery\n noise(P.x, P.z, (P.running ? numbers.stepNoiseRun : P.crouch ? numbers.stepNoiseCrouch : numbers.stepNoiseWalk) * derived.footstepNoise * (wet ? numbers.stepNoiseWater : 1))\n sound('step', P.running ? numbers.stepVolumeRun : numbers.stepVolumeWalk)\n emit('step', { x: P.x, z: P.z, yaw: P.yaw })\n }\n // shove and melee\n if (wasPressed('push') && P.stamina > numbers.shoveCost) {\n P.stamina -= numbers.shoveCost\n shove(viewYaw)\n }\n if (wasPressed('throw')) emit('throw', {})\n if (wasPressed('knife') && P.stamina > numbers.meleeMinStamina) {\n const item = input.melee ?? fist\n P.stamina -= (item.kg ?? 0) > numbers.meleeHeavyKg ? numbers.meleeCostHeavy : numbers.meleeCostLight\n melee(item, viewYaw)\n }\n // panic: chasing agents in sight nearby\n let near = 0\n if (crowd) {\n const n = crowd.count()\n for (let i = 0; i < n; i++) if (crowd.active(i) && crowd.chasing(i)) near += crowd.panicWeight?.(i) ?? 1\n }\n P.panic = clamp(P.panic + (near * numbers.panicGain - (near ? 0 : numbers.panicDecay)) * dt, 0, numbers.panicMax)\n }\n\n return {\n get state() {\n return P\n },\n attributes,\n derived,\n numbers,\n infection,\n update,\n hurt: (amount) => hurt(amount),\n bite: () => bite(),\n grab,\n release: () => release('free'),\n knock(seconds) {\n if (!P.alive) return\n P.downTimer = Math.max(P.downTimer, seconds)\n P.crouch = false\n },\n infect,\n die,\n stage() {\n if (!P.infected || !infection) return 'none'\n return P.infectionTime > infection.deliriumSeconds ? 'delirium' : P.infectionTime > infection.feverSeconds ? 'fever' : 'malaise'\n },\n timeLeft: () => (P.infected && infection ? Math.max(0, infection.deathSeconds - P.infectionTime) : null),\n spreadFactor() {\n const panic = P.panic > derived.composure * numbers.panicSpreadAt ? numbers.panicSpread : 1\n const fever = P.infected && infection && P.infectionTime > infection.feverSeconds ? infection.feverSpread : 1\n return panic * fever * (1 + Math.hypot(P.vx, P.vz) * numbers.moveSpread)\n },\n front,\n on(event, listener) {\n let set = listeners.get(event)\n if (!set) listeners.set(event, (set = new Set()))\n set.add(listener as (event: never) => void)\n return () => void set.delete(listener as (event: never) => void)\n },\n save: () => ({ state: structuredClone(P), attributes }),\n load(save) {\n P = structuredClone(save.state)\n },\n setWorld(next) {\n defaultWorld = next\n },\n }\n}\n","/**\n * Pushing furniture on foot: hold the interaction button against a piece, a timer that grows with its mass fills, and the player then walks with it.\n * Engine-agnostic: the host says where the player wants to go and answers whether the volume of the piece can go there; this says how fast, and when it locks.\n */\n\nexport type FurniturePushPhase = 'idle' | 'grip' | 'push' | 'strain'\nexport type FurniturePushBlock = 'too_heavy' | 'obstacle' | null\n\n/** Every number of the push; a game overrides what it wants (`createFurniturePush(rules)`). */\nexport interface FurniturePushRules {\n /** The most the player's legs put on the floor, newtons: with the friction it says the heaviest thing that moves. */\n readonly forceN: number\n readonly gravity: number\n /** Static friction of a base on a floor, by the material of the piece. */\n readonly frictionByMaterial: Readonly<Record<string, number>>\n readonly defaultFriction: number\n /** The hold before the push: `base + perKg * mass`, at most `max` seconds. */\n readonly gripSeconds: { readonly base: number; readonly perKg: number; readonly max: number }\n /** Metres per second: `max` with nothing on the hands, `min` at the limit of the force. */\n readonly speed: { readonly max: number; readonly min: number }\n /** A press shorter than this is not a push (the host keeps it for a tap, such as grabbing). */\n readonly tapSeconds: number\n /** How long the effort stays after the last step that was refused, so that it does not flicker. */\n readonly strainHoldSeconds: number\n}\n\nexport const FURNITURE_PUSH_DEFAULTS: FurniturePushRules = {\n forceN: 500,\n gravity: 9.81,\n frictionByMaterial: { wood_soft: 0.4, wood_hard: 0.4, mdf: 0.4, plywood: 0.4, steel: 0.35, aluminium: 0.35, cast_iron: 0.4, copper: 0.35, plastic: 0.35, rubber: 0.8, fabric: 0.45, foam: 0.5, ceramic: 0.5, glass: 0.3, tempered_glass: 0.3, brick: 0.6, concrete: 0.65 },\n defaultFriction: 0.45,\n gripSeconds: { base: 0.4, perKg: 0.015, max: 2.5 },\n speed: { max: 1.8, min: 0.35 },\n tapSeconds: 0.2,\n strainHoldSeconds: 0.25,\n}\n\nexport type FurniturePushTarget = { readonly massKg: number; readonly material?: string }\n\nconst frictionOf = (target: FurniturePushTarget, rules: FurniturePushRules): number => (target.material !== undefined ? rules.frictionByMaterial[target.material] : undefined) ?? rules.defaultFriction\n\nconst loadShare = (target: FurniturePushTarget, rules: FurniturePushRules): number => (frictionOf(target, rules) * target.massKg * rules.gravity) / rules.forceN\n\nexport const gripSecondsFor = (massKg: number, rules: FurniturePushRules = FURNITURE_PUSH_DEFAULTS): number => Math.min(rules.gripSeconds.max, rules.gripSeconds.base + rules.gripSeconds.perKg * Math.max(0, massKg))\n\n/** Whether the legs overcome the friction of the piece on the floor. */\nexport const canPush = (target: FurniturePushTarget, rules: FurniturePushRules = FURNITURE_PUSH_DEFAULTS): boolean => loadShare(target, rules) <= 1\n\n/** Metres per second with the piece on the hands: slower the closer it is to the limit of the force, 0 past it. */\nexport const pushSpeedFor = (target: FurniturePushTarget, rules: FurniturePushRules = FURNITURE_PUSH_DEFAULTS): number => {\n const share = loadShare(target, rules)\n return share > 1 ? 0 : rules.speed.max + (rules.speed.min - rules.speed.max) * share\n}\n\nexport type FurniturePushInput = {\n /** Where the player wants to go on the floor: a unit vector, or `[0, 0]` standing. */\n readonly walk: readonly [number, number]\n /** Whether the volume of the piece (and the player behind it) can move by this offset. */\n readonly isFree: (dx: number, dz: number) => boolean\n}\n\nexport type FurniturePushStep = {\n readonly dx: number\n readonly dz: number\n /** The grip closed on this update. */\n readonly engaged: boolean\n /** A step was refused now and the one before was not: the moment the piece hits something. */\n readonly hitObstacle: boolean\n}\n\nexport interface FurniturePush {\n readonly phase: FurniturePushPhase\n /** How far the hold timer is, 0 to 1. */\n readonly progress: number\n readonly block: FurniturePushBlock\n readonly heldSeconds: number\n /** Whether the hold is still short enough to be a tap. */\n readonly isTap: boolean\n begin(target: FurniturePushTarget): void\n release(): void\n update(dt: number, input: FurniturePushInput): FurniturePushStep\n}\n\nconst STILL: FurniturePushStep = { dx: 0, dz: 0, engaged: false, hitObstacle: false }\n\nexport function createFurniturePush(overrides: Partial<FurniturePushRules> = {}): FurniturePush {\n const rules: FurniturePushRules = { ...FURNITURE_PUSH_DEFAULTS, ...overrides }\n let phase: FurniturePushPhase = 'idle'\n let target: FurniturePushTarget = { massKg: 0 }\n let held = 0\n let gripSeconds = 1\n let speed = 0\n let block: FurniturePushBlock = null\n let refused = 0\n let wasRefused = false\n\n const walkWith = (dt: number, input: FurniturePushInput): FurniturePushStep => {\n refused = Math.max(0, refused - dt)\n if (block === 'too_heavy') return STILL\n const [x, z] = input.walk\n if ((x === 0 && z === 0) || dt <= 0) {\n if (refused === 0) {\n phase = 'push'\n block = null\n wasRefused = false\n }\n return STILL\n }\n const dx = x * speed * dt\n const dz = z * speed * dt\n if (input.isFree(dx, dz)) {\n if (refused === 0) {\n phase = 'push'\n block = null\n }\n wasRefused = false\n return { dx, dz, engaged: false, hitObstacle: false }\n }\n const hitObstacle = !wasRefused\n wasRefused = true\n refused = rules.strainHoldSeconds\n phase = 'strain'\n block = 'obstacle'\n return { dx: 0, dz: 0, engaged: false, hitObstacle }\n }\n\n return {\n get phase() {\n return phase\n },\n get progress() {\n return phase === 'idle' ? 0 : Math.min(1, held / gripSeconds)\n },\n get block() {\n return block\n },\n get heldSeconds() {\n return held\n },\n get isTap() {\n return phase === 'grip' && held < rules.tapSeconds\n },\n begin(next) {\n target = next\n phase = 'grip'\n held = 0\n block = null\n refused = 0\n wasRefused = false\n gripSeconds = gripSecondsFor(next.massKg, rules)\n speed = pushSpeedFor(next, rules)\n },\n release() {\n phase = 'idle'\n held = 0\n block = null\n },\n update(dt, input) {\n if (phase === 'idle') return STILL\n held += dt\n if (phase !== 'grip') return walkWith(dt, input)\n if (held < gripSeconds) return STILL\n if (canPush(target, rules)) phase = 'push'\n else {\n phase = 'strain'\n block = 'too_heavy'\n }\n return { ...STILL, engaged: true }\n },\n }\n}\n","import type { KnownDeathCause, PlayerMessageId } from '../types'\n\nexport type PlayerText = Readonly<Record<PlayerMessageId | KnownDeathCause, string>>\n\n/** The game's own words (G 68434, 68452, 68518, 68525-68541, 68547) and the death causes it shows (G 68448, 68454, 68510, 68519, 68539). */\nconst PT_BR: PlayerText = {\n grabbed: 'AGARRADO! Aperte E várias vezes para empurrar ou F para a faca',\n grabbed_drown: 'O AFOGADO TE PUXA PARA O FUNDO! E várias vezes ou F para a faca',\n bitten: 'Você foi mordido. Não há cura.',\n bandaged: 'Curativo feito',\n knife_head: 'Faca na cabeça!',\n knife_miss: 'Errou a facada',\n pushed_off: 'Empurrou!',\n drowning: 'Afogando! Solte-se!',\n no_jaw: 'Sem mandíbula: só arranhou',\n stood_up: 'De pé!',\n infected: 'Morreu infectado',\n killed: 'Morto pela horda',\n bitten_to_death: 'Mordido',\n infection: 'A infecção venceu',\n bled_out: 'Sangrou até a morte',\n hunger_thirst: 'Fome e sede',\n drowned: 'Afogado',\n burned: 'Queimado',\n}\n\nconst EN: PlayerText = {\n grabbed: 'GRABBED! Press E repeatedly to push or F for the knife',\n grabbed_drown: 'THE DROWNED PULLS YOU UNDER! E repeatedly or F for the knife',\n bitten: 'You were bitten. There is no cure.',\n bandaged: 'Wound dressed',\n knife_head: 'Knife to the head!',\n knife_miss: 'The stab missed',\n pushed_off: 'Pushed off!',\n drowning: 'Drowning! Break free!',\n no_jaw: 'No jaw: only a scratch',\n stood_up: 'Back on your feet!',\n infected: 'Died infected',\n killed: 'Killed by the horde',\n bitten_to_death: 'Bitten',\n infection: 'The infection won',\n bled_out: 'Bled to death',\n hunger_thirst: 'Hunger and thirst',\n drowned: 'Drowned',\n burned: 'Burned',\n}\n\nexport const PLAYER_TEXT: Readonly<Record<'en' | 'pt-BR', PlayerText>> = { en: EN, 'pt-BR': PT_BR }\n\n/** The text of a message or death cause id in a locale (`pt-BR` or `en`, the language part is enough); unknown ids come back as they are. */\nexport const playerTextOf = (id: string, locale = 'pt-BR'): string => {\n const table = locale.toLowerCase().startsWith('en') ? EN : PT_BR\n return (table as Readonly<Record<string, string>>)[id] ?? id\n}\n","export type PlayerBenchText = {\n readonly group: string\n readonly name: string\n readonly controls: Readonly<Record<'infection' | 'agility' | 'vigor' | 'seed' | 'hurt' | 'bite' | 'grab' | 'push' | 'knife' | 'bandage' | 'knock' | 'crouch' | 'reset', string>>\n readonly hints: Readonly<Record<'infection' | 'agility' | 'vigor' | 'seed' | 'grab' | 'push', string>>\n readonly metrics: Readonly<Record<'health' | 'stamina' | 'bleeding' | 'wounds' | 'stage' | 'time_left' | 'panic' | 'spread' | 'grab' | 'noise' | 'steps' | 'message', string>>\n readonly stages: Readonly<Record<'none' | 'malaise' | 'fever' | 'delirium' | 'dead', string>>\n readonly scenarios: Readonly<Record<'stamina' | 'bleed_bandage' | 'normal_world' | 'infection_kills' | 'grab_break_free' | 'determinism', string>>\n readonly yes: string\n readonly no: string\n}\n\nconst EN: PlayerBenchText = {\n group: 'Player',\n name: 'Player area',\n controls: {\n infection: 'Individual infection',\n agility: 'Agility',\n vigor: 'Vigor',\n seed: 'Seed',\n hurt: 'Take a hit (10)',\n bite: 'Bite',\n grab: 'Get grabbed',\n push: 'Push (E)',\n knife: 'Knife (F)',\n bandage: 'Bandage (B)',\n knock: 'Knocked down 1.5 s',\n crouch: 'Crouch (C)',\n reset: 'Start again',\n },\n hints: {\n infection: 'Off: a normal world, wounds never infect. On: the game rule (scratch 6%, laceration 22%, bite 100%; fever at 30 s, death at 120 s).',\n agility: 'The sheet: stamina, run speed and footstep noise come from it.',\n vigor: 'The sheet: health, stamina and composure come from it.',\n seed: 'The same seed gives the same wounds and the same knife rolls.',\n grab: 'Something grabs you from behind: 3 s to push it off (6 pushes) or to land the knife (70%).',\n push: 'Shoves what is in front, or pushes off what holds you.',\n },\n metrics: {\n health: 'Health',\n stamina: 'Stamina',\n bleeding: 'Bleeding',\n wounds: 'Wounds',\n stage: 'Infection',\n time_left: 'Time left',\n panic: 'Panic',\n spread: 'Aim spread x',\n grab: 'Grab timer',\n noise: 'Last noise',\n steps: 'Footsteps',\n message: 'Message',\n },\n stages: { none: 'None', malaise: 'Malaise', fever: 'Fever', delirium: 'Delirium', dead: 'Dead' },\n scenarios: {\n stamina: 'Running drains stamina and resting gives it back',\n bleed_bandage: 'A laceration bleeds until it is dressed',\n normal_world: 'In a normal world a bite hurts and bleeds but never infects',\n infection_kills: 'With the infection on, a bite brings fever and kills at its time',\n grab_break_free: 'Six pushes break a grab before the bite',\n determinism: 'The same seed gives the same wounds',\n },\n yes: 'yes',\n no: 'no',\n}\n\nconst PT_BR: PlayerBenchText = {\n group: 'Jogador',\n name: 'Área do jogador',\n controls: {\n infection: 'Infecção individual',\n agility: 'Agilidade',\n vigor: 'Vigor',\n seed: 'Semente',\n hurt: 'Levar um golpe (10)',\n bite: 'Mordida',\n grab: 'Ser agarrado',\n push: 'Empurrar (E)',\n knife: 'Faca (F)',\n bandage: 'Curativo (B)',\n knock: 'Derrubado 1,5 s',\n crouch: 'Agachar (C)',\n reset: 'Recomeçar',\n },\n hints: {\n infection: 'Desligada: mundo normal, ferida nunca infecta. Ligada: a regra do jogo (arranhão 6%, laceração 22%, mordida 100%; febre aos 30 s, morte aos 120 s).',\n agility: 'A ficha: fôlego, velocidade de corrida e ruído dos passos saem dela.',\n vigor: 'A ficha: vida, fôlego e compostura saem dela.',\n seed: 'A mesma semente dá as mesmas feridas e os mesmos golpes de faca.',\n grab: 'Algo te agarra por trás: 3 s para empurrar (6 empurrões) ou acertar a faca (70%).',\n push: 'Empurra o que está na frente, ou se solta do que te segura.',\n },\n metrics: {\n health: 'Vida',\n stamina: 'Fôlego',\n bleeding: 'Sangrando',\n wounds: 'Feridas',\n stage: 'Infecção',\n time_left: 'Tempo restante',\n panic: 'Pânico',\n spread: 'Dispersão x',\n grab: 'Agarrão',\n noise: 'Último ruído',\n steps: 'Passos',\n message: 'Mensagem',\n },\n stages: { none: 'Nenhuma', malaise: 'Mal-estar', fever: 'Febre', delirium: 'Delírio', dead: 'Morto' },\n scenarios: {\n stamina: 'Correr gasta fôlego e descansar devolve',\n bleed_bandage: 'Uma laceração sangra até o curativo',\n normal_world: 'No mundo normal a mordida machuca e sangra, mas não infecta',\n infection_kills: 'Com a infecção ligada, a mordida dá febre e mata no tempo dela',\n grab_break_free: 'Seis empurrões soltam o agarrão antes da mordida',\n determinism: 'A mesma semente dá as mesmas feridas',\n },\n yes: 'sim',\n no: 'não',\n}\n\nexport const playerBenchTextOf = (locale: string): PlayerBenchText => (locale.toLowerCase().startsWith('en') ? EN : PT_BR)\n","import type { BenchChange, ModuleControl, ModuleHost, ModuleMetric, ModuleScenario, TestableModule } from '@adatechnology/game-contracts'\n\nimport { playerTextOf } from '../locales'\nimport { createPlayer } from '../player'\nimport type { Player, PlayerOptions } from '../player'\nimport type { PlayerAction, PlayerCrowd, PlayerInput } from '../types'\nimport { playerBenchTextOf } from './locale'\n\nexport type PlayerTestModuleOptions = PlayerOptions & { readonly locale?: string }\n\n/** What the scenarios use of the context the test room passes. */\nexport interface PlayerScenarioLike {\n expect(condition: boolean, label: string, data?: Record<string, unknown>): void\n}\n\nexport type PlayerTestModule = TestableModule<PlayerScenarioLike> & {\n /** The player in use (replaced when the bench changes the sheet, the seed or the infection). */\n readonly player: Player\n}\n\ntype CameraLike = { position: { x: number; y: number; z: number }; rotation?: { y: number }; getWorldDirection?(target: unknown): { x: number; z: number } }\ntype ThreeLike = { Vector3?: new () => { x: number; y: number; z: number } }\n\nconst MOVING_SPEED = 0.2\nconst SPRINT_SPEED = 3.4\nconst FRAME = 1 / 30\n\n/**\n * One agent standing behind the player for the grab test: the bench has no crowd, so this is the hand that holds. It follows `hold`, takes\n * the shove and the knife, and leaves the count once it lets go.\n */\nconst createGrabber = () => {\n const agent = { x: 0, z: 0, on: false, stunned: 0, hits: 0 }\n const crowd: PlayerCrowd = {\n count: () => (agent.on ? 1 : 0),\n active: () => agent.on,\n x: () => agent.x,\n z: () => agent.z,\n y: () => 0,\n floor: () => 0,\n chasing: () => agent.on,\n down: () => agent.stunned > 0,\n hold(_i, x, z, k) {\n agent.x += (x - agent.x) * k\n agent.z += (z - agent.z) * k\n },\n stun(_i, seconds) {\n agent.stunned = seconds\n agent.on = false\n },\n chase() {\n agent.on = false\n },\n damage() {\n agent.hits += 1\n agent.on = false\n },\n }\n return { agent, crowd }\n}\n\n/**\n * The player area of a test room, against the generic contracts only. The room's camera is the player: where it walks, the player walks; its speed\n * decides walking or running, so stamina, footsteps and their noise follow the viewer. The bench hurts, bites, grabs and knocks the player down,\n * switches the individual infection (off by default: a normal world) and sets the sheet. Footsteps and flesh sounds go to `host.audio`.\n */\nexport function createPlayerTestModule(options: PlayerTestModuleOptions = {}): PlayerTestModule {\n const locale = options.locale ?? 'pt-BR'\n const text = playerBenchTextOf(locale)\n const { locale: _locale, ...playerOptions } = options\n void _locale\n const settings = { infection: options.infection === undefined ? false : options.infection !== false, agility: options.attributes?.agility ?? 5, vigor: options.attributes?.vigor ?? 5, seed: options.seed ?? 1 }\n let host: ModuleHost | null = null\n const grabber = createGrabber()\n let lastNoise = 0\n let steps = 0\n let lastMessage = ''\n let pending: Partial<Record<PlayerAction, boolean>> = {}\n let bandage = false\n let last: { x: number; z: number } | null = null\n const offs: (() => void)[] = []\n\n const build = (): Player => {\n for (const off of offs.splice(0)) off()\n const made = createPlayer({ ...playerOptions, seed: settings.seed, infection: settings.infection, attributes: { ...playerOptions.attributes, agility: settings.agility, vigor: settings.vigor } })\n offs.push(made.on('noise', (e) => void (lastNoise = e.radius)))\n offs.push(made.on('step', () => void (steps += 1)))\n offs.push(made.on('message', (e) => void (lastMessage = playerTextOf(e.id, locale))))\n offs.push(made.on('sound', (e) => void host?.audio?.play({ sound: e.sound, volume: e.volume, position: e.position })))\n offs.push(made.on('died', (e) => host?.log(`player died: ${e.cause}`, { cause: e.cause })))\n lastNoise = 0\n steps = 0\n lastMessage = ''\n return made\n }\n let player = build()\n\n const view = (): { x: number; z: number; yaw: number } | null => {\n const camera = host?.camera as CameraLike | undefined\n if (!camera?.position) return null\n const Vector3 = (host?.THREE as ThreeLike | undefined)?.Vector3\n if (camera.getWorldDirection && Vector3) {\n const look = camera.getWorldDirection(new Vector3())\n return { x: camera.position.x, z: camera.position.z, yaw: Math.atan2(-look.x, -look.z) }\n }\n return { x: camera.position.x, z: camera.position.z, yaw: camera.rotation?.y ?? 0 }\n }\n\n const frame = (dt: number): void => {\n const here = view()\n const speed = here && last && dt > 0 ? Math.hypot(here.x - last.x, here.z - last.z) / dt : 0\n if (here) {\n player.state.x = here.x\n player.state.z = here.z\n }\n const input: PlayerInput = { forward: speed > MOVING_SPEED ? 1 : 0, run: speed > SPRINT_SPEED, yaw: here?.yaw ?? 0, bandage, pressed: pending }\n pending = {}\n bandage = false\n player.update(dt, input, { crowd: grabber.crowd })\n if (here) {\n player.state.x = here.x\n player.state.z = here.z\n last = { x: here.x, z: here.z }\n }\n if (grabber.agent.stunned > 0) grabber.agent.stunned = Math.max(0, grabber.agent.stunned - dt)\n }\n\n const grab = (): void => {\n const P = player.state\n grabber.agent.on = true\n grabber.agent.x = P.x - Math.sin(P.yaw) * player.numbers.grabOffset\n grabber.agent.z = P.z - Math.cos(P.yaw) * player.numbers.grabOffset\n player.grab(0)\n }\n\n const onChange = (change: BenchChange): void => {\n if (change.kind === 'action') {\n const id = change.id\n if (id === 'hurt') player.hurt(10)\n else if (id === 'bite') player.bite()\n else if (id === 'grab') grab()\n else if (id === 'knock') player.knock(1.5)\n else if (id === 'bandage') bandage = true\n else if (id === 'push' || id === 'knife' || id === 'crouch') pending = { ...pending, [id]: true }\n else if (id === 'reset') player = build()\n return\n }\n if (change.kind !== 'control') return\n const { id, value } = change\n if (id === 'infection' && typeof value === 'boolean' && value !== settings.infection) settings.infection = value\n else if ((id === 'agility' || id === 'vigor' || id === 'seed') && typeof value === 'number' && value !== settings[id]) settings[id] = value\n else return\n player = build()\n }\n\n const controls = (): ModuleControl[] => [\n { kind: 'boolean', id: 'infection', name: text.controls.infection, hint: text.hints.infection, default: settings.infection },\n { kind: 'number', id: 'agility', name: text.controls.agility, hint: text.hints.agility, min: 1, max: 8, step: 1, default: settings.agility },\n { kind: 'number', id: 'vigor', name: text.controls.vigor, hint: text.hints.vigor, min: 1, max: 8, step: 1, default: settings.vigor },\n { kind: 'number', id: 'seed', name: text.controls.seed, hint: text.hints.seed, min: 1, max: 9999, step: 1, default: settings.seed },\n { kind: 'action', id: 'hurt', name: text.controls.hurt },\n { kind: 'action', id: 'bite', name: text.controls.bite },\n { kind: 'action', id: 'grab', name: text.controls.grab, hint: text.hints.grab },\n { kind: 'action', id: 'push', name: text.controls.push, hint: text.hints.push },\n { kind: 'action', id: 'knife', name: text.controls.knife },\n { kind: 'action', id: 'bandage', name: text.controls.bandage },\n { kind: 'action', id: 'knock', name: text.controls.knock },\n { kind: 'action', id: 'crouch', name: text.controls.crouch },\n { kind: 'action', id: 'reset', name: text.controls.reset },\n ]\n\n const stageName = (): string => (player.state.alive ? text.stages[player.stage()] : text.stages.dead)\n const metrics = (): ModuleMetric[] => [\n { id: 'health', name: text.metrics.health, digits: 1, max: player.derived.maxHealth, read: () => Math.max(0, player.state.health) },\n { id: 'stamina', name: text.metrics.stamina, digits: 1, max: player.derived.maxStamina, read: () => player.state.stamina },\n { id: 'bleeding', name: text.metrics.bleeding, read: () => (player.state.bleeding ? text.yes : text.no) },\n { id: 'wounds', name: text.metrics.wounds, digits: 0, read: () => player.state.wounds.length },\n { id: 'stage', name: text.metrics.stage, read: stageName },\n { id: 'time_left', name: text.metrics.time_left, unit: 's', digits: 0, read: () => player.timeLeft() ?? 0 },\n { id: 'panic', name: text.metrics.panic, digits: 1, read: () => player.state.panic },\n { id: 'spread', name: text.metrics.spread, digits: 2, read: () => player.spreadFactor() },\n { id: 'grab_timer', name: text.metrics.grab, unit: 's', digits: 1, read: () => (player.state.grabbedBy >= 0 ? player.state.grabTimer : 0) },\n { id: 'noise', name: text.metrics.noise, unit: 'm', digits: 1, read: () => lastNoise },\n { id: 'steps', name: text.metrics.steps, digits: 0, read: () => steps },\n { id: 'message', name: text.metrics.message, read: () => lastMessage },\n ]\n\n // each scenario runs its own player, so the bench's live one is not touched\n const fresh = (extra: PlayerOptions = {}): Player => createPlayer({ ...playerOptions, ...extra })\n const run = (made: Player, seconds: number, input: PlayerInput = {}, crowd?: PlayerCrowd): void => {\n for (let t = 0; t < seconds; t += FRAME) made.update(FRAME, input, crowd ? { crowd } : undefined)\n }\n const scenarios = (): Array<ModuleScenario<PlayerScenarioLike>> => [\n {\n id: 'player_stamina',\n name: text.scenarios.stamina,\n run: ({ expect }) => {\n const made = fresh({ seed: 1 })\n const full = made.state.stamina\n run(made, 4, { forward: 1, run: true })\n const tired = made.state.stamina\n expect(tired < full - 40, 'four seconds of running spend 48 of stamina', { full, tired })\n run(made, 3)\n expect(made.state.stamina > tired, 'standing still gives it back', { tired, rested: made.state.stamina })\n },\n },\n {\n id: 'player_bleed_bandage',\n name: text.scenarios.bleed_bandage,\n run: ({ expect }) => {\n const made = fresh({ seed: 1 })\n made.bite()\n const after = made.state.health\n run(made, 2)\n expect(made.state.bleeding === 1 && made.state.health < after, 'the wound bleeds', { health: made.state.health })\n run(made, FRAME, { bandage: true })\n const dressed = made.state.health\n run(made, 2)\n expect(made.state.bleeding === 0 && made.state.health === dressed, 'dressed, it stops', { health: made.state.health })\n },\n },\n {\n id: 'player_normal_world',\n name: text.scenarios.normal_world,\n run: ({ expect }) => {\n const made = fresh({ seed: 1, infection: false })\n made.bite()\n run(made, 10)\n expect(!made.state.infected && made.state.health < made.derived.maxHealth, 'bitten, hurt, not infected', { health: made.state.health })\n },\n },\n {\n id: 'player_infection_kills',\n name: text.scenarios.infection_kills,\n run: ({ expect }) => {\n const made = fresh({ seed: 1, infection: true })\n made.bite()\n run(made, FRAME, { bandage: true })\n run(made, 40)\n expect(made.stage() === 'fever', 'fever after 30 s', { stage: made.stage() })\n run(made, 90)\n expect(!made.state.alive && made.state.cause === 'infection', 'dead at 120 s', { cause: made.state.cause })\n },\n },\n {\n id: 'player_grab_break_free',\n name: text.scenarios.grab_break_free,\n run: ({ expect }) => {\n const made = fresh({ seed: 1 })\n const { agent, crowd } = createGrabber()\n agent.on = true\n made.grab(0)\n for (let push = 0; push < 6; push++) {\n made.update(FRAME, { pressed: { push: true } }, { crowd })\n made.update(FRAME, {}, { crowd })\n }\n expect(made.state.grabbedBy === -1 && made.state.wounds.length === 0, 'free, and no bite', { grabbedBy: made.state.grabbedBy })\n },\n },\n {\n id: 'player_determinism',\n name: text.scenarios.determinism,\n run: ({ expect }) => {\n const wounds = (seed: number): string => {\n const made = fresh({ seed })\n for (let k = 0; k < 12; k++) made.hurt(1)\n return made.state.wounds.join(',')\n }\n expect(wounds(4) === wounds(4), 'the same seed gives the same wounds')\n expect(wounds(4) !== wounds(5), 'another seed gives others')\n },\n },\n ]\n\n const module: PlayerTestModule = {\n id: 'player_area',\n name: text.name,\n ground: { surface: 'dirt' },\n group: text.group,\n get player() {\n return player\n },\n items: () => [],\n controls: () => controls(),\n metrics: () => metrics(),\n scenarios: () => scenarios(),\n attach(lent) {\n host = lent\n last = null\n const off = lent.bench?.onChange(onChange)\n const offFrame = lent.onFrame(frame)\n return () => {\n off?.()\n offFrame()\n host = null\n }\n },\n }\n return module\n}\n"],"mappings":"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","names":["EN","PT_BR","id"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adatechnology/game-player",
3
- "version": "0.2.4",
3
+ "version": "0.3.0",
4
4
  "license": "MIT",
5
5
  "description": "Pure, seeded player body for games: vitals from an attribute sheet, stamina, wounds and bleeding, an optional individual infection, being grabbed and breaking free, knock-downs, low-wall vaults, footstep noise, panic, shove and melee against any crowd. A literal port of the team game's player. Knows nothing about any game.",
6
6
  "keywords": [
@@ -38,7 +38,7 @@
38
38
  "dist"
39
39
  ],
40
40
  "dependencies": {
41
- "@adatechnology/game-contracts": "0.17.0"
41
+ "@adatechnology/game-contracts": "0.18.0"
42
42
  },
43
43
  "devDependencies": {
44
44
  "@types/node": "^22.10.7",