@adatechnology/game-characters 0.1.6 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -47,6 +47,9 @@ var GameCharacters = (() => {
47
47
  PENETRATION_MODELS: () => PENETRATION_MODELS,
48
48
  PERSON_PRESET: () => PERSON_PRESET,
49
49
  PHYSICAL_PENETRATION: () => PHYSICAL_PENETRATION,
50
+ POSE_CHANNEL_JOINTS: () => POSE_CHANNEL_JOINTS,
51
+ POSE_CLIPS: () => POSE_CLIPS,
52
+ POSE_CLIP_LOCALES: () => POSE_CLIP_LOCALES,
50
53
  PROTECTION_PRESETS: () => PROTECTION_PRESETS,
51
54
  REGION_HIT_POINTS: () => REGION_HIT_POINTS,
52
55
  REGION_SEGMENTS: () => REGION_SEGMENTS,
@@ -63,12 +66,14 @@ var GameCharacters = (() => {
63
66
  applyPreset: () => applyPreset,
64
67
  bleedRateAt: () => bleedRateAt,
65
68
  blendMoves: () => blendMoves,
69
+ clipEventsBetween: () => clipEventsBetween,
66
70
  crawlPose: () => crawlPose,
67
71
  createBloodStream: () => createBloodStream,
68
72
  createBodySpec: () => createBodySpec,
69
73
  createCharacters: () => createCharacters,
70
74
  createConditionTimeline: () => createConditionTimeline,
71
75
  createCorpseLedger: () => createCorpseLedger,
76
+ createPoseClipRegistry: () => createPoseClipRegistry,
72
77
  createRig: () => createRig,
73
78
  createRng: () => createRng,
74
79
  cutOf: () => cutOf,
@@ -80,6 +85,7 @@ var GameCharacters = (() => {
80
85
  emptySample: () => emptySample,
81
86
  encodePoseHeight: () => encodePoseHeight,
82
87
  energyKept: () => energyKept,
88
+ filterPoseChannels: () => filterPoseChannels,
83
89
  humanPose: () => humanPose,
84
90
  isBodyRegion: () => isBodyRegion,
85
91
  isSegmentId: () => isSegmentId,
@@ -87,6 +93,7 @@ var GameCharacters = (() => {
87
93
  layersOn: () => layersOn,
88
94
  lerpPose: () => lerpPose,
89
95
  mergeById: () => mergeById,
96
+ mirrorPoseClip: () => mirrorPoseClip,
90
97
  moveBlendOf: () => moveBlendOf,
91
98
  penetrateLine: () => penetrateLine,
92
99
  penetrationForce: () => penetrationForce,
@@ -96,6 +103,8 @@ var GameCharacters = (() => {
96
103
  removeIds: () => removeIds,
97
104
  resolveDamageRules: () => resolveDamageRules,
98
105
  resolvePoints: () => resolvePoints,
106
+ sampleFirstPersonClip: () => sampleFirstPersonClip,
107
+ samplePoseClip: () => samplePoseClip,
99
108
  segmentNode: () => segmentNode,
100
109
  segmentResistance: () => segmentResistance,
101
110
  segmentsBelow: () => segmentsBelow,
@@ -1363,7 +1372,15 @@ var GameCharacters = (() => {
1363
1372
  };
1364
1373
 
1365
1374
  // src/damage/blast.ts
1366
- var shares = (params, targets, pivot) => targets.map((target) => ({ target, points: params.points * Math.max(0, 1 - distance(params.jointOf(pivot(target)), params.center) / params.radius) })).filter((share) => share.points > params.ops.rules.blast.minimumPoints).sort((a, b) => b.points - a.points);
1375
+ var INJURY_POINTS = 15;
1376
+ var pointsAt = (params, metres) => {
1377
+ const { points, radius, lethalRadius, ops } = params;
1378
+ if (lethalRadius === void 0 || lethalRadius >= radius) return points * Math.max(0, 1 - metres / radius);
1379
+ if (metres <= lethalRadius) return points;
1380
+ const injury = Math.min(points, ops.rules.blast.injuryPoints ?? INJURY_POINTS);
1381
+ return injury * Math.max(0, 1 - (metres - lethalRadius) / (radius - lethalRadius));
1382
+ };
1383
+ var shares = (params, targets, pivot) => targets.map((target) => ({ target, points: pointsAt(params, distance(params.jointOf(pivot(target)), params.center)) })).filter((share) => share.points > params.ops.rules.blast.minimumPoints).sort((a, b) => b.points - a.points);
1367
1384
  var segmentBlast = (params) => {
1368
1385
  const { ops, rule, blow } = params;
1369
1386
  const { blast: blast2, segments } = ops.rules;
@@ -1615,7 +1632,7 @@ var GameCharacters = (() => {
1615
1632
  };
1616
1633
  var blast = ({ ops, hit, setup, localPoint, jointOf }) => {
1617
1634
  const points = hit.points ?? pointsFromEnergy(hit.energy ?? 0, setup.rules);
1618
- const base = { ops, center: localPoint, points, radius: hit.radius ?? 1, jointOf };
1635
+ const base = { ops, center: localPoint, points, radius: hit.radius ?? 1, ...hit.lethalRadius !== void 0 ? { lethalRadius: hit.lethalRadius } : {}, jointOf };
1619
1636
  const common = { cut: hit.cut ?? setup.rules.defaultCut.explosive, damageType: hit.type, model: setup.model, headResistance: HEAD_RESISTANCE };
1620
1637
  const rule = SEGMENT_RULES[setup.rules.segmentRule] ?? kitRule;
1621
1638
  const result = ops.body.detail === "regions" ? regionBlast({ ...base, blow: { ...common, protection: NO_PROTECTION } }) : segmentBlast({ ...base, rule, blow: { ...common, limbFactor: ops.spec.limbFactor } });
@@ -2450,6 +2467,494 @@ var GameCharacters = (() => {
2450
2467
  const apron = random() < APRON_SHARE;
2451
2468
  return { sleeve, hair, headWidth, headHeight, jaw, nose, beard, glasses, cap, capColor, bag, bagColor, torn, apron };
2452
2469
  };
2470
+
2471
+ // src/pose-clips/pose-clip.ts
2472
+ var samplePoseClip = (clip, time) => {
2473
+ const keys = clip.keys;
2474
+ if (keys.length === 0) return {};
2475
+ if (keys.length === 1) return { ...keys[0].pose };
2476
+ let index = 0;
2477
+ while (index < keys.length - 2 && time > keys[index + 1].t) index++;
2478
+ const a = keys[index];
2479
+ const b = keys[index + 1];
2480
+ const k = Math.min(1, Math.max(0, (time - a.t) / (b.t - a.t)));
2481
+ const eased = k * k * (3 - 2 * k);
2482
+ return lerpPose(a.pose, b.pose, eased);
2483
+ };
2484
+ var clipEventsBetween = (clip, from, to) => (clip.events ?? []).filter((event) => event.t > from && event.t <= to).sort((x, y) => x.t - y.t);
2485
+ var POSE_CHANNEL_JOINTS = {
2486
+ full: void 0,
2487
+ upper: ["lean", "twist", "side", "headX", "headY", "headZ", "armR", "armL", "elbR", "elbL", "armRz", "armLz"],
2488
+ lower: ["drop", "legL", "legR", "kneeL", "kneeR"]
2489
+ };
2490
+ var filterPoseChannels = (pose, channels = "full") => {
2491
+ const allowed = POSE_CHANNEL_JOINTS[channels];
2492
+ if (!allowed) return pose;
2493
+ const out = {};
2494
+ for (const name of allowed) if (pose[name] !== void 0) out[name] = pose[name];
2495
+ return out;
2496
+ };
2497
+ var MIRROR_PAIRS = [["armR", "armL"], ["elbR", "elbL"], ["armRz", "armLz"], ["legR", "legL"], ["kneeR", "kneeL"]];
2498
+ var MIRROR_NEGATED = /* @__PURE__ */ new Set(["side", "twist", "headY", "headZ"]);
2499
+ var mirrorPoseClip = (clip, id) => ({
2500
+ ...clip,
2501
+ id,
2502
+ keys: clip.keys.map((key) => {
2503
+ const pose = {};
2504
+ for (const [name, value] of Object.entries(key.pose)) pose[name] = MIRROR_NEGATED.has(name) ? -value : value;
2505
+ for (const [a, b] of MIRROR_PAIRS) {
2506
+ const va = key.pose[a];
2507
+ const vb = key.pose[b];
2508
+ const sign = a === "armRz" ? -1 : 1;
2509
+ if (vb !== void 0) pose[a] = sign * vb;
2510
+ else delete pose[a];
2511
+ if (va !== void 0) pose[b] = sign * va;
2512
+ else delete pose[b];
2513
+ }
2514
+ return { t: key.t, pose };
2515
+ }),
2516
+ ...clip.events ? { events: clip.events.map((event) => ({ ...event })) } : {}
2517
+ });
2518
+
2519
+ // src/presets/pose-clips.json
2520
+ var pose_clips_default = {
2521
+ clips: [
2522
+ {
2523
+ id: "grabbed_bitten_human",
2524
+ source: {
2525
+ file: "site/pages/zumbis-personagens/bestiario.html",
2526
+ scene: "ataque (Agarr\xE3o e mordida)",
2527
+ variable: "HK"
2528
+ },
2529
+ duration: 8,
2530
+ loop: false,
2531
+ channels: "full",
2532
+ keys: [
2533
+ {
2534
+ t: 0,
2535
+ pose: {
2536
+ lean: 0,
2537
+ headY: 0,
2538
+ armL: -0.1,
2539
+ armR: 0.05,
2540
+ elbL: -0.2,
2541
+ elbR: -0.2,
2542
+ drop: 0,
2543
+ kneeL: 0.05,
2544
+ kneeR: 0.05,
2545
+ legL: -0.05,
2546
+ legR: 0.05,
2547
+ headX: 0
2548
+ }
2549
+ },
2550
+ {
2551
+ t: 1.5,
2552
+ pose: {
2553
+ lean: -0.1,
2554
+ headY: -0.6,
2555
+ armL: -0.1,
2556
+ armR: 0.05,
2557
+ elbL: -0.2,
2558
+ elbR: -0.2,
2559
+ drop: 0,
2560
+ kneeL: 0.05,
2561
+ kneeR: 0.05,
2562
+ legL: -0.05,
2563
+ legR: 0.05,
2564
+ headX: -0.1
2565
+ }
2566
+ },
2567
+ {
2568
+ t: 2.1,
2569
+ pose: {
2570
+ lean: -0.3,
2571
+ headY: -0.2,
2572
+ armL: -1.3,
2573
+ armR: -1.2,
2574
+ elbL: -1.4,
2575
+ elbR: -1.5,
2576
+ drop: -0.04,
2577
+ kneeL: 0.25,
2578
+ kneeR: 0.2,
2579
+ legL: -0.3,
2580
+ legR: 0.25,
2581
+ headX: -0.25
2582
+ }
2583
+ },
2584
+ {
2585
+ t: 3.6,
2586
+ pose: {
2587
+ lean: -0.35,
2588
+ headY: 0.3,
2589
+ armL: -1.5,
2590
+ armR: -1,
2591
+ elbL: -0.6,
2592
+ elbR: -1.8,
2593
+ drop: -0.05,
2594
+ kneeL: 0.3,
2595
+ kneeR: 0.2,
2596
+ legL: -0.4,
2597
+ legR: 0.35,
2598
+ headX: -0.2
2599
+ }
2600
+ },
2601
+ {
2602
+ t: 4.3,
2603
+ pose: {
2604
+ lean: -0.2,
2605
+ headY: 0.7,
2606
+ headZ: -0.5,
2607
+ armL: -0.6,
2608
+ armR: -1.9,
2609
+ elbL: -0.4,
2610
+ elbR: -1.2,
2611
+ drop: -0.06,
2612
+ kneeL: 0.3,
2613
+ kneeR: 0.3,
2614
+ legL: -0.3,
2615
+ legR: 0.3,
2616
+ headX: -0.3
2617
+ }
2618
+ },
2619
+ {
2620
+ t: 5.6,
2621
+ pose: {
2622
+ lean: 0.55,
2623
+ headY: 0.4,
2624
+ headZ: -0.3,
2625
+ armL: -0.3,
2626
+ armR: -0.5,
2627
+ elbL: -0.6,
2628
+ elbR: -0.8,
2629
+ drop: -0.5,
2630
+ kneeL: 1.9,
2631
+ kneeR: 1.7,
2632
+ legL: -1.1,
2633
+ legR: -0.9,
2634
+ headX: 0.3
2635
+ }
2636
+ },
2637
+ {
2638
+ t: 8,
2639
+ pose: {
2640
+ lean: 0.6,
2641
+ headY: 0.4,
2642
+ headZ: -0.3,
2643
+ armL: -0.25,
2644
+ armR: -0.45,
2645
+ elbL: -0.6,
2646
+ elbR: -0.8,
2647
+ drop: -0.52,
2648
+ kneeL: 1.95,
2649
+ kneeR: 1.75,
2650
+ legL: -1.1,
2651
+ legR: -0.95,
2652
+ headX: 0.4
2653
+ }
2654
+ }
2655
+ ],
2656
+ events: [
2657
+ {
2658
+ t: 0,
2659
+ type: "phase",
2660
+ data: {
2661
+ label: "pose_clip.grab_bite.phase.approach"
2662
+ }
2663
+ },
2664
+ {
2665
+ t: 1.7,
2666
+ type: "phase",
2667
+ data: {
2668
+ label: "pose_clip.grab_bite.phase.pounce"
2669
+ }
2670
+ },
2671
+ {
2672
+ t: 2.1,
2673
+ type: "phase",
2674
+ data: {
2675
+ label: "pose_clip.grab_bite.phase.grab"
2676
+ }
2677
+ },
2678
+ {
2679
+ t: 4.3,
2680
+ type: "phase",
2681
+ data: {
2682
+ label: "pose_clip.grab_bite.phase.bite"
2683
+ }
2684
+ },
2685
+ {
2686
+ t: 5.6,
2687
+ type: "phase",
2688
+ data: {
2689
+ label: "pose_clip.grab_bite.phase.fall"
2690
+ }
2691
+ },
2692
+ {
2693
+ t: 4.4,
2694
+ type: "impact",
2695
+ data: {
2696
+ kind: "bite",
2697
+ source: "bite.visible=T>4.4 in the scene's step()"
2698
+ }
2699
+ }
2700
+ ]
2701
+ },
2702
+ {
2703
+ id: "grab_bite_zombie",
2704
+ source: {
2705
+ file: "site/pages/zumbis-personagens/bestiario.html",
2706
+ scene: "ataque (Agarr\xE3o e mordida)",
2707
+ variable: "ZK"
2708
+ },
2709
+ duration: 8,
2710
+ loop: false,
2711
+ channels: "full",
2712
+ keys: [
2713
+ {
2714
+ t: 0,
2715
+ pose: {
2716
+ x: -6,
2717
+ lean: 0.75,
2718
+ armL: -1.35,
2719
+ armR: -1.05,
2720
+ elbL: -0.08,
2721
+ elbR: -0.12,
2722
+ headX: -0.55,
2723
+ drop: -0.1,
2724
+ run: 1
2725
+ }
2726
+ },
2727
+ {
2728
+ t: 1.7,
2729
+ pose: {
2730
+ x: -0.9,
2731
+ lean: 0.75,
2732
+ armL: -1.35,
2733
+ armR: -1.05,
2734
+ elbL: -0.08,
2735
+ elbR: -0.12,
2736
+ headX: -0.55,
2737
+ drop: -0.1,
2738
+ run: 1
2739
+ }
2740
+ },
2741
+ {
2742
+ t: 2.1,
2743
+ pose: {
2744
+ x: -0.32,
2745
+ lean: 0.45,
2746
+ armL: -1.65,
2747
+ armR: -1.6,
2748
+ elbL: -0.25,
2749
+ elbR: -0.3,
2750
+ headX: -0.3,
2751
+ drop: -0.08,
2752
+ legL: -0.6,
2753
+ legR: 0.4,
2754
+ kneeL: 0.5,
2755
+ kneeR: 0.6,
2756
+ run: 0
2757
+ }
2758
+ },
2759
+ {
2760
+ t: 3.6,
2761
+ pose: {
2762
+ x: -0.2,
2763
+ lean: 0.35,
2764
+ armL: -1.5,
2765
+ armR: -1.45,
2766
+ elbL: -1.1,
2767
+ elbR: -1.2,
2768
+ headX: -0.2,
2769
+ drop: -0.06,
2770
+ legL: -0.4,
2771
+ legR: 0.3,
2772
+ kneeL: 0.4,
2773
+ kneeR: 0.4,
2774
+ run: 0
2775
+ }
2776
+ },
2777
+ {
2778
+ t: 4.3,
2779
+ pose: {
2780
+ x: -0.1,
2781
+ lean: 0.5,
2782
+ armL: -1.4,
2783
+ armR: -1.3,
2784
+ elbL: -1.5,
2785
+ elbR: -1.5,
2786
+ headX: 0.35,
2787
+ headY: 0.35,
2788
+ drop: -0.08,
2789
+ legL: -0.35,
2790
+ legR: 0.3,
2791
+ kneeL: 0.4,
2792
+ kneeR: 0.4,
2793
+ run: 0
2794
+ }
2795
+ },
2796
+ {
2797
+ t: 5.6,
2798
+ pose: {
2799
+ x: 0,
2800
+ lean: 0.95,
2801
+ armL: -1.2,
2802
+ armR: -1,
2803
+ elbL: -1.4,
2804
+ elbR: -1.3,
2805
+ headX: 0.5,
2806
+ headY: 0.3,
2807
+ drop: -0.45,
2808
+ legL: -1.2,
2809
+ legR: -0.8,
2810
+ kneeL: 1.8,
2811
+ kneeR: 1.5,
2812
+ run: 0
2813
+ }
2814
+ },
2815
+ {
2816
+ t: 8,
2817
+ pose: {
2818
+ x: 0,
2819
+ lean: 1,
2820
+ armL: -1.15,
2821
+ armR: -0.95,
2822
+ elbL: -1.4,
2823
+ elbR: -1.3,
2824
+ headX: 0.55,
2825
+ headY: 0.3,
2826
+ drop: -0.47,
2827
+ legL: -1.2,
2828
+ legR: -0.8,
2829
+ kneeL: 1.85,
2830
+ kneeR: 1.5,
2831
+ run: 0
2832
+ }
2833
+ }
2834
+ ],
2835
+ events: [
2836
+ {
2837
+ t: 0,
2838
+ type: "phase",
2839
+ data: {
2840
+ label: "pose_clip.grab_bite.phase.approach"
2841
+ }
2842
+ },
2843
+ {
2844
+ t: 1.7,
2845
+ type: "phase",
2846
+ data: {
2847
+ label: "pose_clip.grab_bite.phase.pounce"
2848
+ }
2849
+ },
2850
+ {
2851
+ t: 2.1,
2852
+ type: "phase",
2853
+ data: {
2854
+ label: "pose_clip.grab_bite.phase.grab"
2855
+ }
2856
+ },
2857
+ {
2858
+ t: 4.3,
2859
+ type: "phase",
2860
+ data: {
2861
+ label: "pose_clip.grab_bite.phase.bite"
2862
+ }
2863
+ },
2864
+ {
2865
+ t: 5.6,
2866
+ type: "phase",
2867
+ data: {
2868
+ label: "pose_clip.grab_bite.phase.fall"
2869
+ }
2870
+ }
2871
+ ]
2872
+ }
2873
+ ],
2874
+ locales: {
2875
+ "pt-BR": {
2876
+ "pose_clip.grab_bite.phase.approach": "1. Aproxima\xE7\xE3o",
2877
+ "pose_clip.grab_bite.phase.pounce": "2. O bote",
2878
+ "pose_clip.grab_bite.phase.grab": "3. Agarr\xE3o: 3 s para se soltar",
2879
+ "pose_clip.grab_bite.phase.bite": "4. Mordida: infec\xE7\xE3o 100%",
2880
+ "pose_clip.grab_bite.phase.fall": "5. Queda"
2881
+ },
2882
+ en: {
2883
+ "pose_clip.grab_bite.phase.approach": "1. Approach",
2884
+ "pose_clip.grab_bite.phase.pounce": "2. The pounce",
2885
+ "pose_clip.grab_bite.phase.grab": "3. Grab: 3 s to break free",
2886
+ "pose_clip.grab_bite.phase.bite": "4. Bite: 100% infection",
2887
+ "pose_clip.grab_bite.phase.fall": "5. The fall"
2888
+ }
2889
+ }
2890
+ };
2891
+
2892
+ // src/pose-clips/registry.ts
2893
+ var createPoseClipRegistry = (initial = []) => {
2894
+ const clips = /* @__PURE__ */ new Map();
2895
+ const registry = {
2896
+ register(clip) {
2897
+ clips.set(clip.id, clip);
2898
+ return registry;
2899
+ },
2900
+ get: (id) => clips.get(id),
2901
+ list: () => [...clips.values()],
2902
+ remove: (id) => clips.delete(id)
2903
+ };
2904
+ for (const clip of initial) registry.register(clip);
2905
+ return registry;
2906
+ };
2907
+ var POSE_CLIPS = pose_clips_default.clips;
2908
+ var POSE_CLIP_LOCALES = pose_clips_default.locales;
2909
+
2910
+ // src/pose-clips/first-person-clip.ts
2911
+ var ease = (k) => k * k * (3 - 2 * k);
2912
+ var mix = (a, b, k) => a + (b - a) * k;
2913
+ var mixTriple = (a, b, k) => [mix(a[0], b[0], k), mix(a[1], b[1], k), mix(a[2], b[2], k)];
2914
+ var trackOf = (clip, side) => {
2915
+ const out = [];
2916
+ for (const key of clip.keys) {
2917
+ if (side === "L") {
2918
+ if (key.L === "mirror") {
2919
+ if (key.R) out.push({ t: key.t, key: key.R, mirror: true });
2920
+ } else if (key.L) out.push({ t: key.t, key: key.L, mirror: false });
2921
+ } else {
2922
+ const entry = key[side];
2923
+ if (entry) out.push({ t: key.t, key: entry, mirror: false });
2924
+ }
2925
+ }
2926
+ return out.sort((a, b) => a.t - b.t);
2927
+ };
2928
+ var sampleTrack = (track, time) => {
2929
+ if (track.length === 0) return void 0;
2930
+ const first = track[0];
2931
+ const last = track[track.length - 1];
2932
+ const of = (entry) => ({ p: [...entry.key.p], r: [...entry.key.r], grip: entry.key.grip, w: entry.key.w ?? 1, mirror: entry.mirror });
2933
+ if (time <= first.t) return of(first);
2934
+ if (time >= last.t) return of(last);
2935
+ let index = 0;
2936
+ while (index < track.length - 2 && time > track[index + 1].t) index++;
2937
+ const a = track[index];
2938
+ const b = track[index + 1];
2939
+ const k = ease(Math.min(1, Math.max(0, (time - a.t) / (b.t - a.t))));
2940
+ const ga = a.key.grip;
2941
+ const gb = b.key.grip;
2942
+ return {
2943
+ p: mixTriple(a.key.p, b.key.p, k),
2944
+ r: mixTriple(a.key.r, b.key.r, k),
2945
+ grip: ga === void 0 ? gb : gb === void 0 ? ga : mix(ga, gb, k),
2946
+ w: mix(a.key.w ?? 1, b.key.w ?? 1, k),
2947
+ mirror: a.mirror
2948
+ };
2949
+ };
2950
+ var sampleFirstPersonClip = (clip, time) => {
2951
+ const out = {};
2952
+ for (const side of ["R", "L", "F"]) {
2953
+ const sample = sampleTrack(trackOf(clip, side), time);
2954
+ if (sample) out[side] = sample;
2955
+ }
2956
+ return out;
2957
+ };
2453
2958
  return __toCommonJS(index_exports);
2454
2959
  })();
2455
2960
  //# sourceMappingURL=index.global.js.map