@adatechnology/game-characters 0.1.5 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -187,6 +187,13 @@ var createCorpseLedger = (options) => {
187
187
  }
188
188
  return removed;
189
189
  },
190
+ remove(index) {
191
+ const entry = entries[index];
192
+ if (!entry) return void 0;
193
+ entries[index] = entries[entries.length - 1];
194
+ entries.pop();
195
+ return entry.data;
196
+ },
190
197
  clear() {
191
198
  entries.length = 0;
192
199
  }
@@ -1241,7 +1248,15 @@ var regionRule = (ops, blow) => {
1241
1248
  };
1242
1249
 
1243
1250
  // src/damage/blast.ts
1244
- 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);
1245
1260
  var segmentBlast = (params) => {
1246
1261
  const { ops, rule, blow } = params;
1247
1262
  const { blast: blast2, segments } = ops.rules;
@@ -1493,7 +1508,7 @@ var burn = ({ ops, hit, setup, worn }) => {
1493
1508
  };
1494
1509
  var blast = ({ ops, hit, setup, localPoint, jointOf }) => {
1495
1510
  const points = hit.points ?? pointsFromEnergy(hit.energy ?? 0, setup.rules);
1496
- 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 };
1497
1512
  const common = { cut: hit.cut ?? setup.rules.defaultCut.explosive, damageType: hit.type, model: setup.model, headResistance: HEAD_RESISTANCE };
1498
1513
  const rule = SEGMENT_RULES[setup.rules.segmentRule] ?? kitRule;
1499
1514
  const result = ops.body.detail === "regions" ? regionBlast({ ...base, blow: { ...common, protection: NO_PROTECTION } }) : segmentBlast({ ...base, rule, blow: { ...common, limbFactor: ops.spec.limbFactor } });
@@ -2328,6 +2343,494 @@ var drawLook = ({ random, pick, female, outfit, human, params }) => {
2328
2343
  const apron = random() < APRON_SHARE;
2329
2344
  return { sleeve, hair, headWidth, headHeight, jaw, nose, beard, glasses, cap, capColor, bag, bagColor, torn, apron };
2330
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
+ };
2331
2834
  export {
2332
2835
  ARSENAL_RULES,
2333
2836
  palette_exports as AppearancePalette,
@@ -2355,6 +2858,9 @@ export {
2355
2858
  PENETRATION_MODELS,
2356
2859
  PERSON_PRESET,
2357
2860
  PHYSICAL_PENETRATION,
2861
+ POSE_CHANNEL_JOINTS,
2862
+ POSE_CLIPS,
2863
+ POSE_CLIP_LOCALES,
2358
2864
  PROTECTION_PRESETS,
2359
2865
  REGION_HIT_POINTS,
2360
2866
  REGION_SEGMENTS,
@@ -2371,12 +2877,14 @@ export {
2371
2877
  applyPreset,
2372
2878
  bleedRateAt,
2373
2879
  blendMoves,
2880
+ clipEventsBetween,
2374
2881
  crawlPose,
2375
2882
  createBloodStream,
2376
2883
  createBodySpec,
2377
2884
  createCharacters,
2378
2885
  createConditionTimeline,
2379
2886
  createCorpseLedger,
2887
+ createPoseClipRegistry,
2380
2888
  createRig,
2381
2889
  createRng,
2382
2890
  cutOf,
@@ -2388,6 +2896,7 @@ export {
2388
2896
  emptySample,
2389
2897
  encodePoseHeight,
2390
2898
  energyKept,
2899
+ filterPoseChannels,
2391
2900
  humanPose,
2392
2901
  isBodyRegion,
2393
2902
  isSegmentId,
@@ -2395,6 +2904,7 @@ export {
2395
2904
  layersOn,
2396
2905
  lerpPose,
2397
2906
  mergeById,
2907
+ mirrorPoseClip,
2398
2908
  moveBlendOf,
2399
2909
  penetrateLine,
2400
2910
  penetrationForce,
@@ -2404,6 +2914,8 @@ export {
2404
2914
  removeIds,
2405
2915
  resolveDamageRules,
2406
2916
  resolvePoints,
2917
+ sampleFirstPersonClip,
2918
+ samplePoseClip,
2407
2919
  segmentNode,
2408
2920
  segmentResistance,
2409
2921
  segmentsBelow,