@adatechnology/game-contracts 0.22.0 → 0.24.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
@@ -16,6 +16,106 @@ function blastShove(blast, target, options = {}) {
16
16
  return { speed, direction: [direction[0] / length, direction[1] / length, direction[2] / length], distance, falloff };
17
17
  }
18
18
 
19
+ // src/blast-impulse.ts
20
+ var DEFAULT_BLAST_IMPULSE = { bodyArea: 0.7, lift: 0.15, minSpeed: 0.3, tntPerJoule: 0.24 / 2e5 };
21
+ var NEAREST = 0.3;
22
+ function sideOnImpulse(tnt, distance) {
23
+ if (!(tnt > 0)) return 0;
24
+ const w3 = Math.cbrt(tnt);
25
+ const z = Math.max(distance, NEAREST) / w3;
26
+ const scaled = 0.067 * Math.sqrt(1 + (z / 0.23) ** 4) / (z * z * Math.cbrt(1 + (z / 1.55) ** 3));
27
+ return scaled * w3 * 100;
28
+ }
29
+ function bodyImpulse(tnt, distance) {
30
+ if (!(tnt > 0)) return 0;
31
+ const z = Math.max(distance, NEAREST) / Math.cbrt(tnt);
32
+ return sideOnImpulse(tnt, distance) * (2 + 4 / (1 + z * z));
33
+ }
34
+ function blastBodySpeed(tnt, distance, mass, reach = 1, options = {}) {
35
+ const area = options.bodyArea ?? DEFAULT_BLAST_IMPULSE.bodyArea;
36
+ return bodyImpulse(tnt, distance) * area * Math.max(0, reach) / Math.max(mass, 1);
37
+ }
38
+
39
+ // src/blast-knock.ts
40
+ var KNOCK_DOWN_SPEED = 2.5;
41
+ var KNOCKED_DOWN_ANGLE = 1.35;
42
+ var LIE_SECONDS = 1.6;
43
+ var WOUNDED_LIE_SECONDS = 6;
44
+ var FRAGMENT_COVER = 0.5;
45
+ var STUN_SECONDS = 4;
46
+ var STAND_UP_PER_SPEED = 0.25;
47
+ var FALL_SECONDS = 0.25;
48
+ var RISE_SECONDS = 0.6;
49
+ var GROUND_FRICTION = 7;
50
+ var GRAVITY = 9.81;
51
+ var KNOCK_CHEST = 1.1;
52
+ var CHEST = KNOCK_CHEST;
53
+ var bodyMass = (height, build = 1) => 70 * (height / 1.75) ** 2 * build;
54
+ function knockOf(blast, feet, mass, options, impulse = {}) {
55
+ const o = { ...DEFAULT_BLAST_IMPULSE, ...impulse };
56
+ const chest = [feet[0], feet[1] + CHEST, feet[2]];
57
+ const dx = chest[0] - blast.point[0];
58
+ const dy = chest[1] - blast.point[1];
59
+ const dz = chest[2] - blast.point[2];
60
+ const distance = Math.hypot(dx, dy, dz);
61
+ if (!(blast.radius > 0) || distance > blast.radius) return void 0;
62
+ const reach = Math.max(0, Math.min(1, blast.reach ?? 1));
63
+ const tnt = blast.tnt ?? blast.energy * o.tntPerJoule;
64
+ let speed = blastBodySpeed(tnt, distance, mass, reach, o);
65
+ const minSpeed = impulse.minSpeed ?? options?.minSpeed ?? o.minSpeed;
66
+ if (speed < minSpeed) speed = 0;
67
+ const struck = reach >= FRAGMENT_COVER;
68
+ const wounded = struck && blast.lethalRadius !== void 0 && distance <= blast.lethalRadius;
69
+ const edge = 1 - distance / blast.radius;
70
+ const stunSeconds = struck ? STUN_SECONDS * edge * edge * reach : 0;
71
+ if (speed === 0 && !wounded && stunSeconds < 0.25) return void 0;
72
+ const horizontal = Math.hypot(dx, dz);
73
+ const away = horizontal > 1e-4 ? [dx / horizontal, o.lift, dz / horizontal] : [0, 1, 0];
74
+ const length = Math.hypot(away[0], away[1], away[2]);
75
+ const velocity = [away[0] / length * speed, away[1] / length * speed, away[2] / length * speed];
76
+ return {
77
+ velocity,
78
+ airborne: velocity[1] > 0.5,
79
+ lying: 0,
80
+ lieLeft: wounded ? WOUNDED_LIE_SECONDS : 0,
81
+ away: horizontal > 1e-4 ? [dx / horizontal, 0, dz / horizontal] : [0, 0, 0],
82
+ down: speed >= KNOCK_DOWN_SPEED || wounded,
83
+ ...wounded ? { wounded } : {},
84
+ ...stunSeconds >= 0.25 ? { stunSeconds } : {}
85
+ };
86
+ }
87
+ function stepKnock(knock, position, dt, groundAt, alive) {
88
+ const v = knock.velocity;
89
+ position.x += v[0] * dt;
90
+ position.z += v[2] * dt;
91
+ const ground = groundAt(position.x, position.z);
92
+ if (knock.airborne || position.y > ground + 1e-4) {
93
+ v[1] -= GRAVITY * dt;
94
+ position.y += v[1] * dt;
95
+ if (position.y <= ground) {
96
+ position.y = ground;
97
+ v[1] = 0;
98
+ knock.airborne = false;
99
+ }
100
+ } else position.y = ground;
101
+ const horizontal = Math.hypot(v[0], v[2]);
102
+ if (!knock.airborne && horizontal > 0) {
103
+ const slowed = Math.max(0, horizontal - GROUND_FRICTION * dt);
104
+ v[0] *= slowed / horizontal;
105
+ v[2] *= slowed / horizontal;
106
+ }
107
+ const moving = horizontal > 0.05 || knock.airborne;
108
+ if (knock.down) {
109
+ if (moving || knock.lying < 1) knock.lying = Math.min(1, knock.lying + dt / FALL_SECONDS);
110
+ else if (alive) {
111
+ knock.lieLeft = knock.lieLeft > 0 ? knock.lieLeft : LIE_SECONDS + Math.hypot(v[0], v[2]) * STAND_UP_PER_SPEED;
112
+ knock.lieLeft -= dt;
113
+ if (knock.lieLeft <= 0) knock.down = false;
114
+ }
115
+ } else if (knock.lying > 0) knock.lying = Math.max(0, knock.lying - dt / RISE_SECONDS);
116
+ return !moving && !knock.down && knock.lying === 0;
117
+ }
118
+
19
119
  // src/impact-cost.ts
20
120
  var DEFAULT_COST_READS = 1e4;
21
121
  var DEFAULT_COST_CEILING_MS = 50;
@@ -559,6 +659,21 @@ var checkToolClips = (clips, partIds) => {
559
659
  }
560
660
  return { ok: problems.length === 0, problems };
561
661
  };
662
+ var leadClipEvents = (clip) => {
663
+ const events = clip.events ?? [];
664
+ if (!events.some((event) => (event.lead ?? 0) > 0)) return clip;
665
+ let floor = 0;
666
+ const led = events.map((event) => {
667
+ const lead = Math.max(0, Math.min(event.t - floor, event.lead ?? 0));
668
+ const t = event.t - lead;
669
+ floor = Math.max(floor, t);
670
+ if (event.lead === void 0) return event;
671
+ const moved = { ...event, t, data: lead > 0 ? { ...event.data, lead } : { ...event.data } };
672
+ delete moved.lead;
673
+ return moved;
674
+ });
675
+ return { ...clip, events: led };
676
+ };
562
677
  var createToolClipPlayer = (options) => {
563
678
  const { clips, rig, onEvent } = options;
564
679
  let instances = [];
@@ -601,7 +716,7 @@ var createToolClipPlayer = (options) => {
601
716
  }
602
717
  const found = find(step.clip, step.variant);
603
718
  if (!found) return;
604
- const clip = step.duration && step.duration > 0 ? scaleClip(found.clip, step.duration) : found.clip;
719
+ const clip = leadClipEvents(step.duration && step.duration > 0 ? scaleClip(found.clip, step.duration) : found.clip);
605
720
  const interval = options.repeatInterval?.() ?? 0.1;
606
721
  instances = instances.filter((existing) => existing.name !== found.name || existing.delay > 0);
607
722
  for (let round = 0; round < (step.repeat ?? 1); round++) {
@@ -1067,6 +1182,7 @@ export {
1067
1182
  BLOW_IDS,
1068
1183
  BODY_FOLEY_IDS,
1069
1184
  BODY_SOUND_IDS,
1185
+ DEFAULT_BLAST_IMPULSE,
1070
1186
  DEFAULT_BLAST_SHOVE,
1071
1187
  DEFAULT_ENVIRONMENT,
1072
1188
  DEFAULT_IGNITION_RULES,
@@ -1074,11 +1190,15 @@ export {
1074
1190
  DEFERRED_PRIORITY,
1075
1191
  DEFERRED_QUEUE_ID,
1076
1192
  FOOTSTEP_SOUND_IDS,
1193
+ FRAGMENT_COVER,
1077
1194
  FRAME_PHASES,
1078
1195
  GAIT_IDS,
1079
1196
  HEAVY_LANDING_SPEED,
1080
1197
  IMPACT_CONTRACT,
1081
1198
  KIT_ORIGIN_KEY,
1199
+ KNOCKED_DOWN_ANGLE,
1200
+ KNOCK_CHEST,
1201
+ KNOCK_DOWN_SPEED,
1082
1202
  LANDING_IDS,
1083
1203
  LAND_SOUND_IDS,
1084
1204
  MATERIAL_SURFACES,
@@ -1089,7 +1209,10 @@ export {
1089
1209
  TOOL_CLIP,
1090
1210
  TWIST_LIFT,
1091
1211
  applyPatches,
1212
+ blastBodySpeed,
1092
1213
  blastShove,
1214
+ bodyImpulse,
1215
+ bodyMass,
1093
1216
  checkAnimation,
1094
1217
  checkBench,
1095
1218
  checkCategorized,
@@ -1109,7 +1232,9 @@ export {
1109
1232
  ignitionChance,
1110
1233
  isSurfaceId,
1111
1234
  kitOriginOf,
1235
+ knockOf,
1112
1236
  landSoundId,
1237
+ leadClipEvents,
1113
1238
  markKitOrigin,
1114
1239
  mergeById,
1115
1240
  removeIds,
@@ -1122,7 +1247,9 @@ export {
1122
1247
  sealOpener,
1123
1248
  shotExtras,
1124
1249
  shotToHit,
1250
+ sideOnImpulse,
1125
1251
  sparkTargetFactor,
1252
+ stepKnock,
1126
1253
  surfaceOfMaterial,
1127
1254
  swingSoundId,
1128
1255
  toolAnimationStep,