@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.
package/dist/index.js CHANGED
@@ -1248,7 +1248,15 @@ var regionRule = (ops, blow) => {
1248
1248
  };
1249
1249
 
1250
1250
  // src/damage/blast.ts
1251
- 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);
1251
+ var INJURY_POINTS = 15;
1252
+ var pointsAt = (params, metres) => {
1253
+ const { points, radius, lethalRadius, ops } = params;
1254
+ if (lethalRadius === void 0 || lethalRadius >= radius) return points * Math.max(0, 1 - metres / radius);
1255
+ if (metres <= lethalRadius) return points;
1256
+ const injury = Math.min(points, ops.rules.blast.injuryPoints ?? INJURY_POINTS);
1257
+ return injury * Math.max(0, 1 - (metres - lethalRadius) / (radius - lethalRadius));
1258
+ };
1259
+ 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);
1252
1260
  var segmentBlast = (params) => {
1253
1261
  const { ops, rule, blow } = params;
1254
1262
  const { blast: blast2, segments } = ops.rules;
@@ -1500,7 +1508,7 @@ var burn = ({ ops, hit, setup, worn }) => {
1500
1508
  };
1501
1509
  var blast = ({ ops, hit, setup, localPoint, jointOf }) => {
1502
1510
  const points = hit.points ?? pointsFromEnergy(hit.energy ?? 0, setup.rules);
1503
- const base = { ops, center: localPoint, points, radius: hit.radius ?? 1, jointOf };
1511
+ const base = { ops, center: localPoint, points, radius: hit.radius ?? 1, ...hit.lethalRadius !== void 0 ? { lethalRadius: hit.lethalRadius } : {}, jointOf };
1504
1512
  const common = { cut: hit.cut ?? setup.rules.defaultCut.explosive, damageType: hit.type, model: setup.model, headResistance: HEAD_RESISTANCE };
1505
1513
  const rule = SEGMENT_RULES[setup.rules.segmentRule] ?? kitRule;
1506
1514
  const result = ops.body.detail === "regions" ? regionBlast({ ...base, blow: { ...common, protection: NO_PROTECTION } }) : segmentBlast({ ...base, rule, blow: { ...common, limbFactor: ops.spec.limbFactor } });
@@ -2335,6 +2343,494 @@ var drawLook = ({ random, pick, female, outfit, human, params }) => {
2335
2343
  const apron = random() < APRON_SHARE;
2336
2344
  return { sleeve, hair, headWidth, headHeight, jaw, nose, beard, glasses, cap, capColor, bag, bagColor, torn, apron };
2337
2345
  };
2346
+
2347
+ // src/pose-clips/pose-clip.ts
2348
+ var samplePoseClip = (clip, time) => {
2349
+ const keys = clip.keys;
2350
+ if (keys.length === 0) return {};
2351
+ if (keys.length === 1) return { ...keys[0].pose };
2352
+ let index = 0;
2353
+ while (index < keys.length - 2 && time > keys[index + 1].t) index++;
2354
+ const a = keys[index];
2355
+ const b = keys[index + 1];
2356
+ const k = Math.min(1, Math.max(0, (time - a.t) / (b.t - a.t)));
2357
+ const eased = k * k * (3 - 2 * k);
2358
+ return lerpPose(a.pose, b.pose, eased);
2359
+ };
2360
+ var clipEventsBetween = (clip, from, to) => (clip.events ?? []).filter((event) => event.t > from && event.t <= to).sort((x, y) => x.t - y.t);
2361
+ var POSE_CHANNEL_JOINTS = {
2362
+ full: void 0,
2363
+ upper: ["lean", "twist", "side", "headX", "headY", "headZ", "armR", "armL", "elbR", "elbL", "armRz", "armLz"],
2364
+ lower: ["drop", "legL", "legR", "kneeL", "kneeR"]
2365
+ };
2366
+ var filterPoseChannels = (pose, channels = "full") => {
2367
+ const allowed = POSE_CHANNEL_JOINTS[channels];
2368
+ if (!allowed) return pose;
2369
+ const out = {};
2370
+ for (const name of allowed) if (pose[name] !== void 0) out[name] = pose[name];
2371
+ return out;
2372
+ };
2373
+ var MIRROR_PAIRS = [["armR", "armL"], ["elbR", "elbL"], ["armRz", "armLz"], ["legR", "legL"], ["kneeR", "kneeL"]];
2374
+ var MIRROR_NEGATED = /* @__PURE__ */ new Set(["side", "twist", "headY", "headZ"]);
2375
+ var mirrorPoseClip = (clip, id) => ({
2376
+ ...clip,
2377
+ id,
2378
+ keys: clip.keys.map((key) => {
2379
+ const pose = {};
2380
+ for (const [name, value] of Object.entries(key.pose)) pose[name] = MIRROR_NEGATED.has(name) ? -value : value;
2381
+ for (const [a, b] of MIRROR_PAIRS) {
2382
+ const va = key.pose[a];
2383
+ const vb = key.pose[b];
2384
+ const sign = a === "armRz" ? -1 : 1;
2385
+ if (vb !== void 0) pose[a] = sign * vb;
2386
+ else delete pose[a];
2387
+ if (va !== void 0) pose[b] = sign * va;
2388
+ else delete pose[b];
2389
+ }
2390
+ return { t: key.t, pose };
2391
+ }),
2392
+ ...clip.events ? { events: clip.events.map((event) => ({ ...event })) } : {}
2393
+ });
2394
+
2395
+ // src/presets/pose-clips.json
2396
+ var pose_clips_default = {
2397
+ clips: [
2398
+ {
2399
+ id: "grabbed_bitten_human",
2400
+ source: {
2401
+ file: "site/pages/zumbis-personagens/bestiario.html",
2402
+ scene: "ataque (Agarr\xE3o e mordida)",
2403
+ variable: "HK"
2404
+ },
2405
+ duration: 8,
2406
+ loop: false,
2407
+ channels: "full",
2408
+ keys: [
2409
+ {
2410
+ t: 0,
2411
+ pose: {
2412
+ lean: 0,
2413
+ headY: 0,
2414
+ armL: -0.1,
2415
+ armR: 0.05,
2416
+ elbL: -0.2,
2417
+ elbR: -0.2,
2418
+ drop: 0,
2419
+ kneeL: 0.05,
2420
+ kneeR: 0.05,
2421
+ legL: -0.05,
2422
+ legR: 0.05,
2423
+ headX: 0
2424
+ }
2425
+ },
2426
+ {
2427
+ t: 1.5,
2428
+ pose: {
2429
+ lean: -0.1,
2430
+ headY: -0.6,
2431
+ armL: -0.1,
2432
+ armR: 0.05,
2433
+ elbL: -0.2,
2434
+ elbR: -0.2,
2435
+ drop: 0,
2436
+ kneeL: 0.05,
2437
+ kneeR: 0.05,
2438
+ legL: -0.05,
2439
+ legR: 0.05,
2440
+ headX: -0.1
2441
+ }
2442
+ },
2443
+ {
2444
+ t: 2.1,
2445
+ pose: {
2446
+ lean: -0.3,
2447
+ headY: -0.2,
2448
+ armL: -1.3,
2449
+ armR: -1.2,
2450
+ elbL: -1.4,
2451
+ elbR: -1.5,
2452
+ drop: -0.04,
2453
+ kneeL: 0.25,
2454
+ kneeR: 0.2,
2455
+ legL: -0.3,
2456
+ legR: 0.25,
2457
+ headX: -0.25
2458
+ }
2459
+ },
2460
+ {
2461
+ t: 3.6,
2462
+ pose: {
2463
+ lean: -0.35,
2464
+ headY: 0.3,
2465
+ armL: -1.5,
2466
+ armR: -1,
2467
+ elbL: -0.6,
2468
+ elbR: -1.8,
2469
+ drop: -0.05,
2470
+ kneeL: 0.3,
2471
+ kneeR: 0.2,
2472
+ legL: -0.4,
2473
+ legR: 0.35,
2474
+ headX: -0.2
2475
+ }
2476
+ },
2477
+ {
2478
+ t: 4.3,
2479
+ pose: {
2480
+ lean: -0.2,
2481
+ headY: 0.7,
2482
+ headZ: -0.5,
2483
+ armL: -0.6,
2484
+ armR: -1.9,
2485
+ elbL: -0.4,
2486
+ elbR: -1.2,
2487
+ drop: -0.06,
2488
+ kneeL: 0.3,
2489
+ kneeR: 0.3,
2490
+ legL: -0.3,
2491
+ legR: 0.3,
2492
+ headX: -0.3
2493
+ }
2494
+ },
2495
+ {
2496
+ t: 5.6,
2497
+ pose: {
2498
+ lean: 0.55,
2499
+ headY: 0.4,
2500
+ headZ: -0.3,
2501
+ armL: -0.3,
2502
+ armR: -0.5,
2503
+ elbL: -0.6,
2504
+ elbR: -0.8,
2505
+ drop: -0.5,
2506
+ kneeL: 1.9,
2507
+ kneeR: 1.7,
2508
+ legL: -1.1,
2509
+ legR: -0.9,
2510
+ headX: 0.3
2511
+ }
2512
+ },
2513
+ {
2514
+ t: 8,
2515
+ pose: {
2516
+ lean: 0.6,
2517
+ headY: 0.4,
2518
+ headZ: -0.3,
2519
+ armL: -0.25,
2520
+ armR: -0.45,
2521
+ elbL: -0.6,
2522
+ elbR: -0.8,
2523
+ drop: -0.52,
2524
+ kneeL: 1.95,
2525
+ kneeR: 1.75,
2526
+ legL: -1.1,
2527
+ legR: -0.95,
2528
+ headX: 0.4
2529
+ }
2530
+ }
2531
+ ],
2532
+ events: [
2533
+ {
2534
+ t: 0,
2535
+ type: "phase",
2536
+ data: {
2537
+ label: "pose_clip.grab_bite.phase.approach"
2538
+ }
2539
+ },
2540
+ {
2541
+ t: 1.7,
2542
+ type: "phase",
2543
+ data: {
2544
+ label: "pose_clip.grab_bite.phase.pounce"
2545
+ }
2546
+ },
2547
+ {
2548
+ t: 2.1,
2549
+ type: "phase",
2550
+ data: {
2551
+ label: "pose_clip.grab_bite.phase.grab"
2552
+ }
2553
+ },
2554
+ {
2555
+ t: 4.3,
2556
+ type: "phase",
2557
+ data: {
2558
+ label: "pose_clip.grab_bite.phase.bite"
2559
+ }
2560
+ },
2561
+ {
2562
+ t: 5.6,
2563
+ type: "phase",
2564
+ data: {
2565
+ label: "pose_clip.grab_bite.phase.fall"
2566
+ }
2567
+ },
2568
+ {
2569
+ t: 4.4,
2570
+ type: "impact",
2571
+ data: {
2572
+ kind: "bite",
2573
+ source: "bite.visible=T>4.4 in the scene's step()"
2574
+ }
2575
+ }
2576
+ ]
2577
+ },
2578
+ {
2579
+ id: "grab_bite_zombie",
2580
+ source: {
2581
+ file: "site/pages/zumbis-personagens/bestiario.html",
2582
+ scene: "ataque (Agarr\xE3o e mordida)",
2583
+ variable: "ZK"
2584
+ },
2585
+ duration: 8,
2586
+ loop: false,
2587
+ channels: "full",
2588
+ keys: [
2589
+ {
2590
+ t: 0,
2591
+ pose: {
2592
+ x: -6,
2593
+ lean: 0.75,
2594
+ armL: -1.35,
2595
+ armR: -1.05,
2596
+ elbL: -0.08,
2597
+ elbR: -0.12,
2598
+ headX: -0.55,
2599
+ drop: -0.1,
2600
+ run: 1
2601
+ }
2602
+ },
2603
+ {
2604
+ t: 1.7,
2605
+ pose: {
2606
+ x: -0.9,
2607
+ lean: 0.75,
2608
+ armL: -1.35,
2609
+ armR: -1.05,
2610
+ elbL: -0.08,
2611
+ elbR: -0.12,
2612
+ headX: -0.55,
2613
+ drop: -0.1,
2614
+ run: 1
2615
+ }
2616
+ },
2617
+ {
2618
+ t: 2.1,
2619
+ pose: {
2620
+ x: -0.32,
2621
+ lean: 0.45,
2622
+ armL: -1.65,
2623
+ armR: -1.6,
2624
+ elbL: -0.25,
2625
+ elbR: -0.3,
2626
+ headX: -0.3,
2627
+ drop: -0.08,
2628
+ legL: -0.6,
2629
+ legR: 0.4,
2630
+ kneeL: 0.5,
2631
+ kneeR: 0.6,
2632
+ run: 0
2633
+ }
2634
+ },
2635
+ {
2636
+ t: 3.6,
2637
+ pose: {
2638
+ x: -0.2,
2639
+ lean: 0.35,
2640
+ armL: -1.5,
2641
+ armR: -1.45,
2642
+ elbL: -1.1,
2643
+ elbR: -1.2,
2644
+ headX: -0.2,
2645
+ drop: -0.06,
2646
+ legL: -0.4,
2647
+ legR: 0.3,
2648
+ kneeL: 0.4,
2649
+ kneeR: 0.4,
2650
+ run: 0
2651
+ }
2652
+ },
2653
+ {
2654
+ t: 4.3,
2655
+ pose: {
2656
+ x: -0.1,
2657
+ lean: 0.5,
2658
+ armL: -1.4,
2659
+ armR: -1.3,
2660
+ elbL: -1.5,
2661
+ elbR: -1.5,
2662
+ headX: 0.35,
2663
+ headY: 0.35,
2664
+ drop: -0.08,
2665
+ legL: -0.35,
2666
+ legR: 0.3,
2667
+ kneeL: 0.4,
2668
+ kneeR: 0.4,
2669
+ run: 0
2670
+ }
2671
+ },
2672
+ {
2673
+ t: 5.6,
2674
+ pose: {
2675
+ x: 0,
2676
+ lean: 0.95,
2677
+ armL: -1.2,
2678
+ armR: -1,
2679
+ elbL: -1.4,
2680
+ elbR: -1.3,
2681
+ headX: 0.5,
2682
+ headY: 0.3,
2683
+ drop: -0.45,
2684
+ legL: -1.2,
2685
+ legR: -0.8,
2686
+ kneeL: 1.8,
2687
+ kneeR: 1.5,
2688
+ run: 0
2689
+ }
2690
+ },
2691
+ {
2692
+ t: 8,
2693
+ pose: {
2694
+ x: 0,
2695
+ lean: 1,
2696
+ armL: -1.15,
2697
+ armR: -0.95,
2698
+ elbL: -1.4,
2699
+ elbR: -1.3,
2700
+ headX: 0.55,
2701
+ headY: 0.3,
2702
+ drop: -0.47,
2703
+ legL: -1.2,
2704
+ legR: -0.8,
2705
+ kneeL: 1.85,
2706
+ kneeR: 1.5,
2707
+ run: 0
2708
+ }
2709
+ }
2710
+ ],
2711
+ events: [
2712
+ {
2713
+ t: 0,
2714
+ type: "phase",
2715
+ data: {
2716
+ label: "pose_clip.grab_bite.phase.approach"
2717
+ }
2718
+ },
2719
+ {
2720
+ t: 1.7,
2721
+ type: "phase",
2722
+ data: {
2723
+ label: "pose_clip.grab_bite.phase.pounce"
2724
+ }
2725
+ },
2726
+ {
2727
+ t: 2.1,
2728
+ type: "phase",
2729
+ data: {
2730
+ label: "pose_clip.grab_bite.phase.grab"
2731
+ }
2732
+ },
2733
+ {
2734
+ t: 4.3,
2735
+ type: "phase",
2736
+ data: {
2737
+ label: "pose_clip.grab_bite.phase.bite"
2738
+ }
2739
+ },
2740
+ {
2741
+ t: 5.6,
2742
+ type: "phase",
2743
+ data: {
2744
+ label: "pose_clip.grab_bite.phase.fall"
2745
+ }
2746
+ }
2747
+ ]
2748
+ }
2749
+ ],
2750
+ locales: {
2751
+ "pt-BR": {
2752
+ "pose_clip.grab_bite.phase.approach": "1. Aproxima\xE7\xE3o",
2753
+ "pose_clip.grab_bite.phase.pounce": "2. O bote",
2754
+ "pose_clip.grab_bite.phase.grab": "3. Agarr\xE3o: 3 s para se soltar",
2755
+ "pose_clip.grab_bite.phase.bite": "4. Mordida: infec\xE7\xE3o 100%",
2756
+ "pose_clip.grab_bite.phase.fall": "5. Queda"
2757
+ },
2758
+ en: {
2759
+ "pose_clip.grab_bite.phase.approach": "1. Approach",
2760
+ "pose_clip.grab_bite.phase.pounce": "2. The pounce",
2761
+ "pose_clip.grab_bite.phase.grab": "3. Grab: 3 s to break free",
2762
+ "pose_clip.grab_bite.phase.bite": "4. Bite: 100% infection",
2763
+ "pose_clip.grab_bite.phase.fall": "5. The fall"
2764
+ }
2765
+ }
2766
+ };
2767
+
2768
+ // src/pose-clips/registry.ts
2769
+ var createPoseClipRegistry = (initial = []) => {
2770
+ const clips = /* @__PURE__ */ new Map();
2771
+ const registry = {
2772
+ register(clip) {
2773
+ clips.set(clip.id, clip);
2774
+ return registry;
2775
+ },
2776
+ get: (id) => clips.get(id),
2777
+ list: () => [...clips.values()],
2778
+ remove: (id) => clips.delete(id)
2779
+ };
2780
+ for (const clip of initial) registry.register(clip);
2781
+ return registry;
2782
+ };
2783
+ var POSE_CLIPS = pose_clips_default.clips;
2784
+ var POSE_CLIP_LOCALES = pose_clips_default.locales;
2785
+
2786
+ // src/pose-clips/first-person-clip.ts
2787
+ var ease = (k) => k * k * (3 - 2 * k);
2788
+ var mix = (a, b, k) => a + (b - a) * k;
2789
+ var mixTriple = (a, b, k) => [mix(a[0], b[0], k), mix(a[1], b[1], k), mix(a[2], b[2], k)];
2790
+ var trackOf = (clip, side) => {
2791
+ const out = [];
2792
+ for (const key of clip.keys) {
2793
+ if (side === "L") {
2794
+ if (key.L === "mirror") {
2795
+ if (key.R) out.push({ t: key.t, key: key.R, mirror: true });
2796
+ } else if (key.L) out.push({ t: key.t, key: key.L, mirror: false });
2797
+ } else {
2798
+ const entry = key[side];
2799
+ if (entry) out.push({ t: key.t, key: entry, mirror: false });
2800
+ }
2801
+ }
2802
+ return out.sort((a, b) => a.t - b.t);
2803
+ };
2804
+ var sampleTrack = (track, time) => {
2805
+ if (track.length === 0) return void 0;
2806
+ const first = track[0];
2807
+ const last = track[track.length - 1];
2808
+ const of = (entry) => ({ p: [...entry.key.p], r: [...entry.key.r], grip: entry.key.grip, w: entry.key.w ?? 1, mirror: entry.mirror });
2809
+ if (time <= first.t) return of(first);
2810
+ if (time >= last.t) return of(last);
2811
+ let index = 0;
2812
+ while (index < track.length - 2 && time > track[index + 1].t) index++;
2813
+ const a = track[index];
2814
+ const b = track[index + 1];
2815
+ const k = ease(Math.min(1, Math.max(0, (time - a.t) / (b.t - a.t))));
2816
+ const ga = a.key.grip;
2817
+ const gb = b.key.grip;
2818
+ return {
2819
+ p: mixTriple(a.key.p, b.key.p, k),
2820
+ r: mixTriple(a.key.r, b.key.r, k),
2821
+ grip: ga === void 0 ? gb : gb === void 0 ? ga : mix(ga, gb, k),
2822
+ w: mix(a.key.w ?? 1, b.key.w ?? 1, k),
2823
+ mirror: a.mirror
2824
+ };
2825
+ };
2826
+ var sampleFirstPersonClip = (clip, time) => {
2827
+ const out = {};
2828
+ for (const side of ["R", "L", "F"]) {
2829
+ const sample = sampleTrack(trackOf(clip, side), time);
2830
+ if (sample) out[side] = sample;
2831
+ }
2832
+ return out;
2833
+ };
2338
2834
  export {
2339
2835
  ARSENAL_RULES,
2340
2836
  palette_exports as AppearancePalette,
@@ -2362,6 +2858,9 @@ export {
2362
2858
  PENETRATION_MODELS,
2363
2859
  PERSON_PRESET,
2364
2860
  PHYSICAL_PENETRATION,
2861
+ POSE_CHANNEL_JOINTS,
2862
+ POSE_CLIPS,
2863
+ POSE_CLIP_LOCALES,
2365
2864
  PROTECTION_PRESETS,
2366
2865
  REGION_HIT_POINTS,
2367
2866
  REGION_SEGMENTS,
@@ -2378,12 +2877,14 @@ export {
2378
2877
  applyPreset,
2379
2878
  bleedRateAt,
2380
2879
  blendMoves,
2880
+ clipEventsBetween,
2381
2881
  crawlPose,
2382
2882
  createBloodStream,
2383
2883
  createBodySpec,
2384
2884
  createCharacters,
2385
2885
  createConditionTimeline,
2386
2886
  createCorpseLedger,
2887
+ createPoseClipRegistry,
2387
2888
  createRig,
2388
2889
  createRng,
2389
2890
  cutOf,
@@ -2395,6 +2896,7 @@ export {
2395
2896
  emptySample,
2396
2897
  encodePoseHeight,
2397
2898
  energyKept,
2899
+ filterPoseChannels,
2398
2900
  humanPose,
2399
2901
  isBodyRegion,
2400
2902
  isSegmentId,
@@ -2402,6 +2904,7 @@ export {
2402
2904
  layersOn,
2403
2905
  lerpPose,
2404
2906
  mergeById,
2907
+ mirrorPoseClip,
2405
2908
  moveBlendOf,
2406
2909
  penetrateLine,
2407
2910
  penetrationForce,
@@ -2411,6 +2914,8 @@ export {
2411
2914
  removeIds,
2412
2915
  resolveDamageRules,
2413
2916
  resolvePoints,
2917
+ sampleFirstPersonClip,
2918
+ samplePoseClip,
2414
2919
  segmentNode,
2415
2920
  segmentResistance,
2416
2921
  segmentsBelow,