@adatechnology/game-weapons-three 0.17.0 → 0.18.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.
Files changed (46) hide show
  1. package/assets/weapon-references.json +1385 -0
  2. package/assets/weapon-svg/CREDITS.md +1 -1
  3. package/assets/weapon-svg/credits.html +1 -1
  4. package/assets/weapon-svg/generated/accuracy_l96a1.svg +1 -0
  5. package/assets/weapon-svg/generated/aks_74u.svg +1 -0
  6. package/assets/weapon-svg/generated/brass_knuckles.svg +1 -0
  7. package/assets/weapon-svg/generated/bt_mp9.svg +1 -0
  8. package/assets/weapon-svg/generated/colt_python.svg +1 -0
  9. package/assets/weapon-svg/generated/famas.svg +1 -0
  10. package/assets/weapon-svg/generated/fn_m240b.svg +1 -0
  11. package/assets/weapon-svg/generated/fn_ps90.svg +1 -0
  12. package/assets/weapon-svg/generated/fn_scar_l.svg +1 -0
  13. package/assets/weapon-svg/generated/hk_g36.svg +1 -1
  14. package/assets/weapon-svg/generated/hk_g36c.svg +1 -1
  15. package/assets/weapon-svg/generated/hk_g36k.svg +1 -1
  16. package/assets/weapon-svg/generated/hk_usp.svg +1 -0
  17. package/assets/weapon-svg/generated/iwi_tavor.svg +1 -0
  18. package/assets/weapon-svg/generated/kabar.svg +1 -0
  19. package/assets/weapon-svg/generated/katana.svg +1 -0
  20. package/assets/weapon-svg/generated/l85a2.svg +1 -0
  21. package/assets/weapon-svg/generated/m1_garand.svg +1 -0
  22. package/assets/weapon-svg/generated/m32_mgl.svg +1 -0
  23. package/assets/weapon-svg/generated/mauser_kar98k.svg +1 -0
  24. package/assets/weapon-svg/generated/mg42.svg +1 -0
  25. package/assets/weapon-svg/generated/mossberg_590.svg +1 -0
  26. package/assets/weapon-svg/generated/mp40.svg +1 -0
  27. package/assets/weapon-svg/generated/ppsh_41.svg +1 -0
  28. package/assets/weapon-svg/generated/semtex.svg +1 -0
  29. package/assets/weapon-svg/generated/sig_sauer_p320.svg +1 -0
  30. package/assets/weapon-svg/generated/smoke_grenade.svg +1 -0
  31. package/assets/weapon-svg/generated/vss_vintorez.svg +1 -0
  32. package/assets/weapon-svg/generated/walther_p99.svg +1 -0
  33. package/assets/weapon-svg/generated/winchester_1887.svg +1 -0
  34. package/assets/weapon-svg/manifest.json +108 -0
  35. package/dist/{chunk-BDYIF7JD.js → chunk-V47DJ55G.js} +9467 -5838
  36. package/dist/chunk-V47DJ55G.js.map +1 -0
  37. package/dist/index.d.ts +10 -6
  38. package/dist/index.global.js +24012 -18516
  39. package/dist/index.global.js.map +1 -1
  40. package/dist/index.js +5 -1
  41. package/dist/index.js.map +1 -1
  42. package/dist/{testing-BKDGK6cq.d.ts → testing-CRjxCHxK.d.ts} +39 -5
  43. package/dist/testing.d.ts +1 -1
  44. package/dist/testing.js +1 -1
  45. package/package.json +9 -9
  46. package/dist/chunk-BDYIF7JD.js.map +0 -1
package/dist/index.js CHANGED
@@ -36,6 +36,7 @@ import {
36
36
  buildCasing,
37
37
  buildExplosiveModel,
38
38
  buildFlyingRocket,
39
+ buildHandheldModel,
39
40
  buildItemWeaponModel,
40
41
  buildModeledProp,
41
42
  buildProp,
@@ -60,6 +61,7 @@ import {
60
61
  explosivesTextOf,
61
62
  fitAttachmentModels,
62
63
  hasExplosiveModel,
64
+ hasHandheldModel,
63
65
  hasThrowableModel,
64
66
  hasWeaponModel,
65
67
  itemModelOfWeapon,
@@ -82,7 +84,7 @@ import {
82
84
  worldExplosiveItem,
83
85
  worldExplosiveShell,
84
86
  worldExplosiveValve
85
- } from "./chunk-BDYIF7JD.js";
87
+ } from "./chunk-V47DJ55G.js";
86
88
 
87
89
  // src/projectile-model.ts
88
90
  import { markKitOrigin } from "@adatechnology/game-contracts";
@@ -151,6 +153,7 @@ export {
151
153
  buildCartridge,
152
154
  buildCasing,
153
155
  buildExplosiveModel,
156
+ buildHandheldModel,
154
157
  buildItemWeaponModel,
155
158
  buildModeledProp,
156
159
  buildProp,
@@ -176,6 +179,7 @@ export {
176
179
  explosivesTextOf,
177
180
  fitAttachmentModels,
178
181
  hasExplosiveModel,
182
+ hasHandheldModel,
179
183
  hasThrowableModel,
180
184
  hasWeaponModel,
181
185
  itemModelOfWeapon,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/projectile-model.ts","../src/weapon-props.ts"],"sourcesContent":["import { markKitOrigin } from '@adatechnology/game-contracts'\nimport type * as THREE_NS from 'three'\n\nimport { buildWeaponModelById } from './models'\nimport { buildExplosiveModel } from './models/explosives'\nimport { modelKit } from './models/kit'\nimport { buildFlyingRocket } from './models/launcher-rounds'\n\n/** What a host asks for a thrown or set down explosive: the weapon in the hand, the explosive it carries and how it is used (`rocket`, `grenade`, `molotov`, `charge`). */\nexport interface ProjectileQuery {\n readonly weapon: string\n readonly explosive?: string | undefined\n readonly kind: string\n}\n\n/** The model of a projectile and the axis along its length. */\nexport interface ProjectileModel {\n readonly model: THREE_NS.Object3D\n readonly axis: [number, number, number]\n}\n\n/**\n * The model of what a weapon throws or fires, drawn by the same code as the weapon itself: the round of a rocket launcher (the RPG-7's PG-7V, the Carl Gustaf's 84 mm round, the rocket of\n * the disposable tubes), long axis +x, and the explosives of the gallery (the M67, the molotov, the pipe bomb, the dynamite, the C4, the Claymore, the flashbang), centred, axis +y.\n * Answers `null` where the gallery has no model (the 40 mm grenade of a launcher), and a host keeps its primitive for it.\n */\nexport function projectileModel(THREE: typeof THREE_NS, query: ProjectileQuery): ProjectileModel | null {\n if (query.kind !== 'rocket') return explosiveProjectile(THREE, query)\n const launcher = buildWeaponModelById(THREE, query.weapon)\n if (!launcher || launcher.parts.family !== 'rocket') return null\n const round = launcher.parts.makeRound ? launcher.parts.makeRound() : buildFlyingRocket(modelKit(THREE), launcher.parts.launcherType)\n return { model: round, axis: [1, 0, 0] }\n}\n\n// a thrown or set down explosive the gallery drew: its model centred on its middle (it tumbles about it in flight), standing axis +y\nfunction explosiveProjectile(THREE: typeof THREE_NS, query: ProjectileQuery): ProjectileModel | null {\n const model = query.explosive === undefined ? undefined : buildExplosiveModel(THREE, query.explosive)\n if (!model) return null\n const centre = new THREE.Box3().setFromObject(model).getCenter(new THREE.Vector3())\n const holder = markKitOrigin(new THREE.Group(), { owner: 'game-weapons-three', kind: 'explosive', id: model.name })\n holder.name = model.name\n model.position.sub(centre)\n holder.add(model)\n return { model: holder, axis: [0, 1, 0] }\n}\n","import { applyPatches, mergeById, removeIds } from '@adatechnology/game-contracts'\nimport type { DeepPartial } from '@adatechnology/game-contracts'\n\nimport { SHIPPED_WEAPON_ITEM_MODELS, weaponPropsOver } from './weapon-item-model'\nimport type { WeaponItemModel, WeaponProps } from './weapon-item-model'\n\nexport interface WeaponPropsOptions {\n /** Item model overrides by weapon id, added to the shipped ones (`null` keeps the low-poly prop); later packs replace earlier ones. */\n readonly packs?: readonly Readonly<Record<string, WeaponItemModel | null>>[]\n /** Changes to an override by weapon id, merged field by field. */\n readonly patch?: Readonly<Record<string, DeepPartial<WeaponItemModel>>>\n /** Weapon ids whose override is taken out (the weapon id itself is then the item model id). */\n readonly remove?: readonly string[]\n}\n\ntype Entry = { readonly id: string; readonly model: WeaponItemModel }\n\n/** A set of weapon prop overrides of its own: the shipped ones plus `packs`, `patch` and `remove`. Nothing is shared with any other set on the page. */\nexport function createWeaponProps(options: WeaponPropsOptions = {}): WeaponProps {\n const entryOf = ([id, model]: readonly [string, WeaponItemModel | null]): Entry => ({ id, model: model ?? { item: '' } })\n const entries = mergeById<Entry>(SHIPPED_WEAPON_ITEM_MODELS.map(entryOf), (options.packs ?? []).flatMap((pack) => Object.entries(pack).map(entryOf)))\n const patches: Record<string, { model: DeepPartial<WeaponItemModel> }> = {}\n for (const [id, model] of Object.entries(options.patch ?? {})) patches[id] = { model }\n applyPatches(entries, patches)\n removeIds(entries, options.remove)\n return weaponPropsOver(new Map([...entries].map(([id, entry]) => [id, entry.model])))\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,qBAAqB;AA0BvB,SAAS,gBAAgB,OAAwB,OAAgD;AACtG,MAAI,MAAM,SAAS,SAAU,QAAO,oBAAoB,OAAO,KAAK;AACpE,QAAM,WAAW,qBAAqB,OAAO,MAAM,MAAM;AACzD,MAAI,CAAC,YAAY,SAAS,MAAM,WAAW,SAAU,QAAO;AAC5D,QAAM,QAAQ,SAAS,MAAM,YAAY,SAAS,MAAM,UAAU,IAAI,kBAAkB,SAAS,KAAK,GAAG,SAAS,MAAM,YAAY;AACpI,SAAO,EAAE,OAAO,OAAO,MAAM,CAAC,GAAG,GAAG,CAAC,EAAE;AACzC;AAGA,SAAS,oBAAoB,OAAwB,OAAgD;AACnG,QAAM,QAAQ,MAAM,cAAc,SAAY,SAAY,oBAAoB,OAAO,MAAM,SAAS;AACpG,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,SAAS,IAAI,MAAM,KAAK,EAAE,cAAc,KAAK,EAAE,UAAU,IAAI,MAAM,QAAQ,CAAC;AAClF,QAAM,SAAS,cAAc,IAAI,MAAM,MAAM,GAAG,EAAE,OAAO,sBAAsB,MAAM,aAAa,IAAI,MAAM,KAAK,CAAC;AAClH,SAAO,OAAO,MAAM;AACpB,QAAM,SAAS,IAAI,MAAM;AACzB,SAAO,IAAI,KAAK;AAChB,SAAO,EAAE,OAAO,QAAQ,MAAM,CAAC,GAAG,GAAG,CAAC,EAAE;AAC1C;;;AC5CA,SAAS,cAAc,WAAW,iBAAiB;AAkB5C,SAAS,kBAAkB,UAA8B,CAAC,GAAgB;AAC/E,QAAM,UAAU,CAAC,CAAC,IAAI,KAAK,OAAyD,EAAE,IAAI,OAAO,SAAS,EAAE,MAAM,GAAG,EAAE;AACvH,QAAM,UAAU,UAAiB,2BAA2B,IAAI,OAAO,IAAI,QAAQ,SAAS,CAAC,GAAG,QAAQ,CAAC,SAAS,OAAO,QAAQ,IAAI,EAAE,IAAI,OAAO,CAAC,CAAC;AACpJ,QAAM,UAAmE,CAAC;AAC1E,aAAW,CAAC,IAAI,KAAK,KAAK,OAAO,QAAQ,QAAQ,SAAS,CAAC,CAAC,EAAG,SAAQ,EAAE,IAAI,EAAE,MAAM;AACrF,eAAa,SAAS,OAAO;AAC7B,YAAU,SAAS,QAAQ,MAAM;AACjC,SAAO,gBAAgB,IAAI,IAAI,CAAC,GAAG,OAAO,EAAE,IAAI,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,IAAI,MAAM,KAAK,CAAC,CAAC,CAAC;AACtF;","names":[]}
1
+ {"version":3,"sources":["../src/projectile-model.ts","../src/weapon-props.ts"],"sourcesContent":["import { markKitOrigin } from '@adatechnology/game-contracts'\nimport type * as THREE_NS from 'three'\n\nimport { buildWeaponModelById } from './models'\nimport { buildExplosiveModel } from './models/explosives'\nimport { modelKit } from './models/kit'\nimport { buildFlyingRocket } from './models/launcher-rounds'\n\n/** What a host asks for a thrown or set down explosive: the weapon in the hand, the explosive it carries and how it is used (`rocket`, `grenade`, `molotov`, `charge`). */\nexport interface ProjectileQuery {\n readonly weapon: string\n readonly explosive?: string | undefined\n readonly kind: string\n}\n\n/** The model of a projectile and the axis along its length. */\nexport interface ProjectileModel {\n readonly model: THREE_NS.Object3D\n readonly axis: [number, number, number]\n}\n\n/**\n * The model of what a weapon throws or fires, drawn by the same code as the weapon itself: the round of a rocket launcher (the RPG-7's PG-7V, the Carl Gustaf's 84 mm round, the rocket of\n * the disposable tubes), long axis +x, and the explosives of the gallery (the M67, the molotov, the pipe bomb, the dynamite, the C4, the Claymore, the flashbang), centred, axis +y.\n * Answers `null` where the gallery has no model (the 40 mm grenade of a launcher), and a host keeps its primitive for it.\n */\nexport function projectileModel(THREE: typeof THREE_NS, query: ProjectileQuery): ProjectileModel | null {\n if (query.kind !== 'rocket') return explosiveProjectile(THREE, query)\n const launcher = buildWeaponModelById(THREE, query.weapon)\n if (!launcher || launcher.parts.family !== 'rocket') return null\n const round = launcher.parts.makeRound ? launcher.parts.makeRound() : buildFlyingRocket(modelKit(THREE), launcher.parts.launcherType)\n return { model: round, axis: [1, 0, 0] }\n}\n\n// a thrown or set down explosive the gallery drew: its model centred on its middle (it tumbles about it in flight), standing axis +y\nfunction explosiveProjectile(THREE: typeof THREE_NS, query: ProjectileQuery): ProjectileModel | null {\n const model = query.explosive === undefined ? undefined : buildExplosiveModel(THREE, query.explosive)\n if (!model) return null\n const centre = new THREE.Box3().setFromObject(model).getCenter(new THREE.Vector3())\n const holder = markKitOrigin(new THREE.Group(), { owner: 'game-weapons-three', kind: 'explosive', id: model.name })\n holder.name = model.name\n model.position.sub(centre)\n holder.add(model)\n return { model: holder, axis: [0, 1, 0] }\n}\n","import { applyPatches, mergeById, removeIds } from '@adatechnology/game-contracts'\nimport type { DeepPartial } from '@adatechnology/game-contracts'\n\nimport { SHIPPED_WEAPON_ITEM_MODELS, weaponPropsOver } from './weapon-item-model'\nimport type { WeaponItemModel, WeaponProps } from './weapon-item-model'\n\nexport interface WeaponPropsOptions {\n /** Item model overrides by weapon id, added to the shipped ones (`null` keeps the low-poly prop); later packs replace earlier ones. */\n readonly packs?: readonly Readonly<Record<string, WeaponItemModel | null>>[]\n /** Changes to an override by weapon id, merged field by field. */\n readonly patch?: Readonly<Record<string, DeepPartial<WeaponItemModel>>>\n /** Weapon ids whose override is taken out (the weapon id itself is then the item model id). */\n readonly remove?: readonly string[]\n}\n\ntype Entry = { readonly id: string; readonly model: WeaponItemModel }\n\n/** A set of weapon prop overrides of its own: the shipped ones plus `packs`, `patch` and `remove`. Nothing is shared with any other set on the page. */\nexport function createWeaponProps(options: WeaponPropsOptions = {}): WeaponProps {\n const entryOf = ([id, model]: readonly [string, WeaponItemModel | null]): Entry => ({ id, model: model ?? { item: '' } })\n const entries = mergeById<Entry>(SHIPPED_WEAPON_ITEM_MODELS.map(entryOf), (options.packs ?? []).flatMap((pack) => Object.entries(pack).map(entryOf)))\n const patches: Record<string, { model: DeepPartial<WeaponItemModel> }> = {}\n for (const [id, model] of Object.entries(options.patch ?? {})) patches[id] = { model }\n applyPatches(entries, patches)\n removeIds(entries, options.remove)\n return weaponPropsOver(new Map([...entries].map(([id, entry]) => [id, entry.model])))\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,qBAAqB;AA0BvB,SAAS,gBAAgB,OAAwB,OAAgD;AACtG,MAAI,MAAM,SAAS,SAAU,QAAO,oBAAoB,OAAO,KAAK;AACpE,QAAM,WAAW,qBAAqB,OAAO,MAAM,MAAM;AACzD,MAAI,CAAC,YAAY,SAAS,MAAM,WAAW,SAAU,QAAO;AAC5D,QAAM,QAAQ,SAAS,MAAM,YAAY,SAAS,MAAM,UAAU,IAAI,kBAAkB,SAAS,KAAK,GAAG,SAAS,MAAM,YAAY;AACpI,SAAO,EAAE,OAAO,OAAO,MAAM,CAAC,GAAG,GAAG,CAAC,EAAE;AACzC;AAGA,SAAS,oBAAoB,OAAwB,OAAgD;AACnG,QAAM,QAAQ,MAAM,cAAc,SAAY,SAAY,oBAAoB,OAAO,MAAM,SAAS;AACpG,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,SAAS,IAAI,MAAM,KAAK,EAAE,cAAc,KAAK,EAAE,UAAU,IAAI,MAAM,QAAQ,CAAC;AAClF,QAAM,SAAS,cAAc,IAAI,MAAM,MAAM,GAAG,EAAE,OAAO,sBAAsB,MAAM,aAAa,IAAI,MAAM,KAAK,CAAC;AAClH,SAAO,OAAO,MAAM;AACpB,QAAM,SAAS,IAAI,MAAM;AACzB,SAAO,IAAI,KAAK;AAChB,SAAO,EAAE,OAAO,QAAQ,MAAM,CAAC,GAAG,GAAG,CAAC,EAAE;AAC1C;;;AC5CA,SAAS,cAAc,WAAW,iBAAiB;AAkB5C,SAAS,kBAAkB,UAA8B,CAAC,GAAgB;AAC/E,QAAM,UAAU,CAAC,CAAC,IAAI,KAAK,OAAyD,EAAE,IAAI,OAAO,SAAS,EAAE,MAAM,GAAG,EAAE;AACvH,QAAM,UAAU,UAAiB,2BAA2B,IAAI,OAAO,IAAI,QAAQ,SAAS,CAAC,GAAG,QAAQ,CAAC,SAAS,OAAO,QAAQ,IAAI,EAAE,IAAI,OAAO,CAAC,CAAC;AACpJ,QAAM,UAAmE,CAAC;AAC1E,aAAW,CAAC,IAAI,KAAK,KAAK,OAAO,QAAQ,QAAQ,SAAS,CAAC,CAAC,EAAG,SAAQ,EAAE,IAAI,EAAE,MAAM;AACrF,eAAa,SAAS,OAAO;AAC7B,YAAU,SAAS,QAAQ,MAAM;AACjC,SAAO,gBAAgB,IAAI,IAAI,CAAC,GAAG,OAAO,EAAE,IAAI,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,IAAI,MAAM,KAAK,CAAC,CAAC,CAAC;AACtF;","names":[]}
@@ -1,4 +1,4 @@
1
- import { HostTool, HandPose, EffectSink, HostEvent, HandTargets, MuzzlePose, TestableModule, AreaPlacement, DestructionEvent, Hit, Vec3 as Vec3$1, ModuleControl, ModuleLayer, ModuleMetric, ModuleHost } from '@adatechnology/game-contracts';
1
+ import { HostTool, HandPose, EffectSink, ToolHand, HostEvent, HandTargets, MuzzlePose, TestableModule, AreaPlacement, DestructionEvent, Hit, Vec3 as Vec3$1, ModuleControl, ModuleLayer, ModuleMetric, ModuleHost } from '@adatechnology/game-contracts';
2
2
  import { CaseType, CaliberDef, ReloadStageId, WeaponEvent, MountKind, AttachmentDef, FittedAttachment, Arsenal, WeaponDef, ExplosiveDef } from '@adatechnology/game-weapons';
3
3
  import { SampleDefaults, SfxManifest, SoundBank, AudioEngine } from '@adatechnology/game-audio';
4
4
  import * as THREE_NS from 'three';
@@ -928,6 +928,8 @@ interface ModelOptions {
928
928
  h?: number;
929
929
  gl?: number;
930
930
  deagle?: number;
931
+ /** A pistol drawn from its photo instead of by style: `p320`, `usp` or `p99` (see `pistol-design.ts`). */
932
+ design?: string;
931
933
  /** Metal and furniture finish. */
932
934
  steel?: number;
933
935
  stain?: number;
@@ -963,6 +965,8 @@ interface ModelOptions {
963
965
  ar?: number;
964
966
  ak?: number;
965
967
  g3?: number;
968
+ /** The Heckler & Koch G36 family: its polymer receiver, skeletal stock (`stock: 'g36'`), handguard, and on top the carry handle with optics (`carry`) or the long rail. */
969
+ g36?: number;
966
970
  charge?: number;
967
971
  rail?: number;
968
972
  jacket?: number;
@@ -977,10 +981,16 @@ interface ModelOptions {
977
981
  heat?: number;
978
982
  /** Chambers of the revolver cylinder (default 6): the capacity of the weapon. */
979
983
  chambers?: number;
984
+ /** The Colt Python: ventilated rib, full underlug, walnut grip (see `revolver-python.ts`). */
985
+ python?: number;
980
986
  bayo?: number;
981
987
  rod?: number;
982
988
  bands?: number;
983
989
  shot?: number;
990
+ /** The body a bullpup is drawn with when it is not the Steyr AUG (`famas`, `tavor`, `sa80`). */
991
+ look?: string;
992
+ /** The Winchester 1887 lever-action shotgun (its own receiver, lever loop and stock). */
993
+ m1887?: number;
984
994
  /** Launcher type: `rpg`, `m72`, `at4`, `carl`, `flame`, `flameDIY`. */
985
995
  lt?: string;
986
996
  }
@@ -1005,7 +1015,7 @@ interface ModelFrames {
1005
1015
  underbarrel?: readonly [number, number];
1006
1016
  }
1007
1017
  /** The moving mechanism of a model, which picks its fire, reload and clear motion. */
1008
- type ModelFamily = 'pistol' | 'revolver' | 'rifle' | 'semiint' | 'semi12' | 'p90' | 'belt' | 'pump' | 'lever' | 'bolt' | 'boltmag' | 'break' | 'rocket' | 'flame';
1018
+ type ModelFamily = 'pistol' | 'revolver' | 'rifle' | 'semiint' | 'semi12' | 'p90' | 'belt' | 'pump' | 'lever' | 'bolt' | 'boltmag' | 'break' | 'rocket' | 'flame' | 'cylinder';
1009
1019
  /** The named parts a model exposes to the animation: pivots and marks inside the model, never copies. */
1010
1020
  interface ModelParts {
1011
1021
  family: ModelFamily;
@@ -1035,6 +1045,8 @@ interface ModelParts {
1035
1045
  cover?: THREE_NS.Object3D;
1036
1046
  crane?: THREE_NS.Object3D;
1037
1047
  cylinder?: THREE_NS.Object3D;
1048
+ /** The vertical grip under the barrel where the support hand takes a long gun that has one (the MGL). */
1049
+ foreGrip?: THREE_NS.Object3D;
1038
1050
  chambers?: THREE_NS.Object3D[];
1039
1051
  barrels?: THREE_NS.Object3D;
1040
1052
  breech?: THREE_NS.Object3D[];
@@ -1095,6 +1107,7 @@ declare const createMaterials: (THREE: Three) => {
1095
1107
  olive: THREE_NS.MeshStandardMaterial;
1096
1108
  tan: THREE_NS.MeshStandardMaterial;
1097
1109
  wood: THREE_NS.MeshStandardMaterial;
1110
+ beech: THREE_NS.MeshStandardMaterial;
1098
1111
  woodL: THREE_NS.MeshStandardMaterial;
1099
1112
  brass: THREE_NS.MeshStandardMaterial;
1100
1113
  copper: THREE_NS.MeshStandardMaterial;
@@ -1126,9 +1139,14 @@ declare const createMaterials: (THREE: Three) => {
1126
1139
  dynamite: THREE_NS.MeshStandardMaterial;
1127
1140
  c4: THREE_NS.MeshStandardMaterial;
1128
1141
  wire: THREE_NS.MeshStandardMaterial;
1142
+ /** The Semtex putty and the green band of an M18 smoke canister. */
1143
+ semtex: THREE_NS.MeshStandardMaterial;
1144
+ smokeBand: THREE_NS.MeshStandardMaterial;
1145
+ cellophane: THREE_NS.MeshStandardMaterial;
1129
1146
  /** Magazine finishes named by the options. */
1130
1147
  bakelite: THREE_NS.MeshStandardMaterial;
1131
1148
  polyMag: THREE_NS.MeshStandardMaterial;
1149
+ smoke: THREE_NS.MeshStandardMaterial;
1132
1150
  };
1133
1151
  type ModelMaterials = ReturnType<typeof createMaterials>;
1134
1152
  /**
@@ -1287,6 +1305,8 @@ interface WeaponFxOptions {
1287
1305
  contact?: LaserRaycast;
1288
1306
  /** Where the body holds the tool (`ModuleHost.holdFrame`): third person draws it there at its real size. */
1289
1307
  bodyHold?: () => HandPose | null;
1308
+ /** Where the body holds a tool in the left hand (`ModuleHost.holdFrame('L')`), for the left hand's weapon with a weapon in each hand; without it, a body's left shoulder under the eye. */
1309
+ leftBodyHold?: () => HandPose | null;
1290
1310
  /** Whether the view is the player's own eye: the gallery's guns are then framed in the view (`VIEW_HOLD`) instead of held on the body. */
1291
1311
  firstPerson?: () => boolean;
1292
1312
  /** The lens the host draws the first-person layer with (`ModuleHost.setViewmodelFov`): the gun in the hands sets the one of its family, and null when it leaves the view. */
@@ -1306,6 +1326,10 @@ interface WeaponFxOptions {
1306
1326
  lights?: LightBudget;
1307
1327
  /** The host's pools (`host.pools`): the burning droplets and the ground flames of a flamethrower take their geometry and material from them; without them each makes its own (deprecated, removed in the next major). */
1308
1328
  pools?: RenderPools;
1329
+ /** The hand this presentation draws the tool in (default `R`); `L` is the left hand's tool with a tool in each hand (`HostTool.offHand`): held out to the left, the hand on the mirror of the grip. */
1330
+ hand?: ToolHand;
1331
+ /** True while the other hand holds a tool of its own: the tool is held in this hand alone, out to its side, and never brought to the eye. */
1332
+ oneHand?: () => boolean;
1309
1333
  }
1310
1334
 
1311
1335
  /** The weapon in the hands, its fire and reload motion, ejected casings and dropped magazines, and their sounds. */
@@ -1317,12 +1341,17 @@ interface WeaponFx {
1317
1341
  setCondition(condition: string): void;
1318
1342
  /** Where the hands take the weapon (world space, read every frame after `update`): the grip and the forend of the model, or the handle of the generic prop; null with nothing in the hands. */
1319
1343
  handTargets(): HandTargets | null;
1320
- /** The muzzle of the weapon in the hands as drawn now (world space): the gallery model's mark, or the front of the generic prop; null for a tool that fires no shot. */
1321
- muzzle(): MuzzlePose | null;
1344
+ /**
1345
+ * The muzzle of the weapon in the hands as drawn now (world space): the gallery model's mark, or the front of the generic prop; null for a tool that fires no shot. `hand: 'L'` is the
1346
+ * one of the left hand's weapon with a weapon in each hand.
1347
+ */
1348
+ muzzle(hand?: ToolHand): MuzzlePose | null;
1322
1349
  /** What is drawn (casings, magazines, muzzle flash): change a field and the next event follows it. */
1323
1350
  readonly layers: FxLayers;
1324
1351
  /** Weapon shown in the hands, or null. */
1325
1352
  readonly inHand: string | null;
1353
+ /** Weapon shown in the left hand with a weapon in each hand (`HostTool.offHand`), or null. */
1354
+ readonly inLeftHand: string | null;
1326
1355
  /** The clips of the model playing now with the seconds each lasts (scaled to the rule's duration): which reload variant went (`reload` or `reload_empty`...). */
1327
1356
  readonly clips: ReadonlyArray<{
1328
1357
  name: string;
@@ -1336,6 +1365,7 @@ interface WeaponFx {
1336
1365
  /**
1337
1366
  * The presentation of the tool in the hands. The weapons the gallery drew (`MODEL_ENTRIES`) get their model and the clips the rule's events call for
1338
1367
  * (fire, cycle, jam, clear, safety, the seven reloads); the generic archetypes keep their low-poly prop.
1368
+ * With a tool in each hand (`HostTool.offHand`, events with `hand: 'L'`) the left hand gets presentations of its own.
1339
1369
  */
1340
1370
  declare function createWeaponFx(options: WeaponFxOptions): WeaponFx;
1341
1371
 
@@ -1366,6 +1396,10 @@ type WeaponModelDef = Pick<WeaponDef, 'id' | 'category' | 'mass'> & Partial<Pick
1366
1396
  /** The gallery model of the explosive a throwable carries (the frag grenade's M67, the molotov, the dynamite...), or undefined for any other weapon. */
1367
1397
  /** Whether the gallery drew the explosive a throwable carries. */
1368
1398
  declare const hasThrowableModel: (def: Partial<Pick<WeaponDef, "action">>) => boolean;
1399
+ /** Whether the kit drew the melee weapon itself (the KA-BAR, the katana, the brass knuckles). */
1400
+ declare const hasHandheldModel: (def: Pick<WeaponDef, "id">) => boolean;
1401
+ /** The model of a melee weapon the kit drew, lying as the item models do (see `buildMeleeModel`), or undefined for any other weapon. */
1402
+ declare const buildHandheldModel: (THREE: typeof THREE_NS, def: Pick<WeaponDef, "id">) => THREE_NS.Group | undefined;
1369
1403
  declare const buildThrowableModel: (THREE: typeof THREE_NS, def: Partial<Pick<WeaponDef, "action">>) => THREE_NS.Group | undefined;
1370
1404
  /** The set behind `registerWeaponItemModel`, `itemModelOfWeapon`, `buildItemWeaponModel` and `buildWeaponModel`, created on first use. */
1371
1405
  declare const defaultWeaponProps: () => WeaponProps;
@@ -1728,4 +1762,4 @@ declare function createExplosivesTestModule(options?: ExplosivesTestModuleOption
1728
1762
  readonly bench: ReturnType<typeof createExplosivesBench>;
1729
1763
  };
1730
1764
 
1731
- export { WEAPON_ITEM_PREFIX as $, type AttachmentModelRegistry as A, type GunshotInput as B, CLASS_REFERENCE_ENERGY as C, DEFAULT_ENERGY_CURVE as D, EXPLOSIVES_AREA_ID as E, type FlybySound as F, GAME_DISTANCE_CURVE as G, type GunshotPlayed as H, type ItemModels as I, type ItemModelRequest as J, MECHANICAL_SOUNDS as K, type LaserRaycast as L, type ModelOptions as M, MOUNTED_M134_ITEM_ID as N, type MechanicalSoundId as O, type ModelMaterials as P, type MountFrame as Q, RELOAD_SAMPLE as R, RELOAD_SAMPLE_HITS as S, type ShotExtras as T, type ShotSound as U, type ShotSoundClass as V, type WeaponProps as W, type ShotSoundInput as X, type ShotSoundOptions as Y, type SoundClassDef as Z, type SoundStep as _, type WeaponItemModel as a, WEIGHT_INTENSITY as a0, type WeaponAudio as a1, type WeaponAudioOptions as a2, type WeaponFx as a3, type WeaponFxOptions as a4, type WeaponModelDef as a5, type WeaponSampleOptions as a6, type WeaponsTestModuleOptions as a7, buildItemWeaponModel as a8, buildThrowableModel as a9, buildWeaponModel as aa, computeCasingSound as ab, computeFlyby as ac, computeGunshot as ad, computeShotSound as ae, createExplosivesTestModule as af, createWeaponAudio as ag, createWeaponFx as ah, createWeaponsTestModule as ai, defaultWeaponProps as aj, deriveFrames as ak, explosivesTextOf as al, hasThrowableModel as am, itemModelOfWeapon as an, mechanicalSoundOf as ao, modelKit as ap, mountFrame as aq, registerWeaponItemModel as ar, weaponSampleBank as as, weaponSampleDefaults as at, weaponsLayout as au, type WeaponModel as b, type ModelKit as c, type ModelParts as d, type ModelFamily as e, type AttachmentBuildContext as f, type AttachmentModel as g, type AttachmentModelBuilder as h, COUNTER_ITEM_ID as i, CUES_IN_SAMPLE as j, type CasingSound as k, type CuePlayed as l, DEFAULT_EXPLOSIVES_SCENE as m, type DistanceCurve as n, EXPLOSIVES_TEXT as o, type EnergyCurve as p, type ExplosivesRoom as q, type ExplosivesScene as r, type ExplosivesTestModuleOptions as s, type ExplosivesText as t, type FxLayers as u, GAME_SOUND_CLASSES as v, GUNSHOT_PROFILES as w, GUNSHOT_SAMPLE as x, GUNSHOT_SAMPLE_IDS as y, type Gunshot as z };
1765
+ export { WEAPON_ITEM_PREFIX as $, type AttachmentModelRegistry as A, type GunshotInput as B, CLASS_REFERENCE_ENERGY as C, DEFAULT_ENERGY_CURVE as D, EXPLOSIVES_AREA_ID as E, type FlybySound as F, GAME_DISTANCE_CURVE as G, type GunshotPlayed as H, type ItemModels as I, type ItemModelRequest as J, MECHANICAL_SOUNDS as K, type LaserRaycast as L, type ModelOptions as M, MOUNTED_M134_ITEM_ID as N, type MechanicalSoundId as O, type ModelMaterials as P, type MountFrame as Q, RELOAD_SAMPLE as R, RELOAD_SAMPLE_HITS as S, type ShotExtras as T, type ShotSound as U, type ShotSoundClass as V, type WeaponProps as W, type ShotSoundInput as X, type ShotSoundOptions as Y, type SoundClassDef as Z, type SoundStep as _, type WeaponItemModel as a, WEIGHT_INTENSITY as a0, type WeaponAudio as a1, type WeaponAudioOptions as a2, type WeaponFx as a3, type WeaponFxOptions as a4, type WeaponModelDef as a5, type WeaponSampleOptions as a6, type WeaponsTestModuleOptions as a7, buildHandheldModel as a8, buildItemWeaponModel as a9, buildThrowableModel as aa, buildWeaponModel as ab, computeCasingSound as ac, computeFlyby as ad, computeGunshot as ae, computeShotSound as af, createExplosivesTestModule as ag, createWeaponAudio as ah, createWeaponFx as ai, createWeaponsTestModule as aj, defaultWeaponProps as ak, deriveFrames as al, explosivesTextOf as am, hasHandheldModel as an, hasThrowableModel as ao, itemModelOfWeapon as ap, mechanicalSoundOf as aq, modelKit as ar, mountFrame as as, registerWeaponItemModel as at, weaponSampleBank as au, weaponSampleDefaults as av, weaponsLayout as aw, type WeaponModel as b, type ModelKit as c, type ModelParts as d, type ModelFamily as e, type AttachmentBuildContext as f, type AttachmentModel as g, type AttachmentModelBuilder as h, COUNTER_ITEM_ID as i, CUES_IN_SAMPLE as j, type CasingSound as k, type CuePlayed as l, DEFAULT_EXPLOSIVES_SCENE as m, type DistanceCurve as n, EXPLOSIVES_TEXT as o, type EnergyCurve as p, type ExplosivesRoom as q, type ExplosivesScene as r, type ExplosivesTestModuleOptions as s, type ExplosivesText as t, type FxLayers as u, GAME_SOUND_CLASSES as v, GUNSHOT_PROFILES as w, GUNSHOT_SAMPLE as x, GUNSHOT_SAMPLE_IDS as y, type Gunshot as z };
package/dist/testing.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { i as COUNTER_ITEM_ID, m as DEFAULT_EXPLOSIVES_SCENE, E as EXPLOSIVES_AREA_ID, o as EXPLOSIVES_TEXT, q as ExplosivesRoom, r as ExplosivesScene, s as ExplosivesTestModuleOptions, t as ExplosivesText, N as MOUNTED_M134_ITEM_ID, $ as WEAPON_ITEM_PREFIX, a7 as WeaponsTestModuleOptions, af as createExplosivesTestModule, ai as createWeaponsTestModule, al as explosivesTextOf, au as weaponsLayout } from './testing-BKDGK6cq.js';
1
+ export { i as COUNTER_ITEM_ID, m as DEFAULT_EXPLOSIVES_SCENE, E as EXPLOSIVES_AREA_ID, o as EXPLOSIVES_TEXT, q as ExplosivesRoom, r as ExplosivesScene, s as ExplosivesTestModuleOptions, t as ExplosivesText, N as MOUNTED_M134_ITEM_ID, $ as WEAPON_ITEM_PREFIX, a7 as WeaponsTestModuleOptions, ag as createExplosivesTestModule, aj as createWeaponsTestModule, am as explosivesTextOf, aw as weaponsLayout } from './testing-CRjxCHxK.js';
2
2
  import '@adatechnology/game-contracts';
3
3
  import '@adatechnology/game-weapons';
4
4
  import '@adatechnology/game-audio';
package/dist/testing.js CHANGED
@@ -9,7 +9,7 @@ import {
9
9
  createWeaponsTestModule,
10
10
  explosivesTextOf,
11
11
  weaponsLayout
12
- } from "./chunk-BDYIF7JD.js";
12
+ } from "./chunk-V47DJ55G.js";
13
13
  export {
14
14
  COUNTER_ITEM_ID,
15
15
  DEFAULT_EXPLOSIVES_SCENE,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adatechnology/game-weapons-three",
3
- "version": "0.17.0",
3
+ "version": "0.18.0",
4
4
  "license": "MIT AND CC-BY-SA-4.0 AND CC-BY-SA-3.0 AND CC-BY-3.0 AND CC0-1.0 AND LicenseRef-Public-Domain",
5
5
  "description": "three.js presentation for @adatechnology/game-weapons: the real models of the Galeria 3D do Arsenal (78 weapons, a cartridge and a case per calibre), the weapon in the hands playing the tool-animation clips (fire, burst, cycle, jam, clear, safety and the seven reloads), ejected casings and dropped magazines, worn-metal conditions, synthesized sounds, and the weapons test area (counters with every weapon) as a TestableModule.",
6
6
  "keywords": [
@@ -44,15 +44,15 @@
44
44
  "assets"
45
45
  ],
46
46
  "dependencies": {
47
- "@adatechnology/game-audio": "^0.9.1",
48
- "@adatechnology/game-contracts": "^0.27.0",
49
- "@adatechnology/game-floorplan-three": "^0.10.2",
50
- "@adatechnology/game-items-three": "^0.7.5",
47
+ "@adatechnology/game-audio": "^0.9.2",
48
+ "@adatechnology/game-floorplan-three": "^0.10.3",
49
+ "@adatechnology/game-contracts": "^0.28.0",
51
50
  "@adatechnology/game-render-three": "^0.2.0",
52
51
  "@adatechnology/game-shapes-three": "^0.3.1",
53
- "@adatechnology/game-vfx": "^0.8.0",
54
- "@adatechnology/game-weapons": "^0.8.0",
55
- "@adatechnology/game-vfx-three": "^0.7.2"
52
+ "@adatechnology/game-vfx": "^0.10.0",
53
+ "@adatechnology/game-items-three": "^0.7.6",
54
+ "@adatechnology/game-vfx-three": "^0.7.4",
55
+ "@adatechnology/game-weapons": "^0.9.0"
56
56
  },
57
57
  "peerDependencies": {
58
58
  "three": "^0.160.0"
@@ -65,7 +65,7 @@
65
65
  "tsup": "^8.5.1",
66
66
  "typescript": "^5.7.3",
67
67
  "vitest": "^3.2.4",
68
- "@adatechnology/game-test-room": "^0.28.0",
68
+ "@adatechnology/game-test-room": "^0.29.0",
69
69
  "@adatechnology/golden-tool": "^0.0.0"
70
70
  },
71
71
  "scripts": {