@adatechnology/game-vehicles 0.1.12 → 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/README.md CHANGED
@@ -266,3 +266,7 @@ scene.add(c.root)
266
266
  ### Contrato de destruição
267
267
 
268
268
  `createVehicleDestructible(kit, c, opções)` faz um veículo construído seguir o `DestructibleImpl` de `@adatechnology/game-contracts`: cada zona de dano vira uma peça com material, as peças mecânicas (bateria, alternador, câmbio, freios, direção, amortecedores, pneus, retrovisores, engate) são acrescentadas, as juntas (dobradiça, parafuso, solda) se desfazem por desgaste ou com a chave inglesa, e as peças saem do veículo e caem. `status()` diz o que a mecânica faz (freios, direção, bateria, câmbio). Os nomes em português estão em `locales/pt-BR.json` (`mechanics.*`).
269
+
270
+ ## Light mode and damageable parts
271
+
272
+ `createVehicleKit({ lod })` takes the settings of the light mode (`defaultLodSettings`: every number can be overridden). `kit.build(key, state, zones, { lod: true })` builds the same vehicle with fewer triangles (rounded boxes with one ring, coarser lofts, grilles and generators, interiors tagged `userData.skipLite`) and puts the switch back; with it off nothing changes. `kit.damageables(c, matrix?)` lists the metal, glass, rubber and fuel parts of a built vehicle as `Box3` boxes (`kit.damageableKinds` maps zone types to parts and can be extended).
package/dist/index.d.ts CHANGED
@@ -1,5 +1,59 @@
1
1
  import { ToolKind, JointKind, Vec3, MaterialId, DestructibleImpl, AnimationClipSpec } from '@adatechnology/game-contracts';
2
2
 
3
+ /**
4
+ * Light mode ("lite"): the same vehicles with fewer triangles, for a whole street of them. Port of the `[LOD]` hooks of the team's Frota Leve
5
+ * (frota-leve.js lines 21-65, 232-257, 1205-1221, 14155-14170). Every number is a setting; with `on` false nothing changes, so every golden
6
+ * of the full-detail build stays byte for byte the same.
7
+ */
8
+
9
+ interface LodSettings {
10
+ /** Light mode is active for the builds that run now. Set by `kit.build(key, state, zones, { lod: true })`. */
11
+ on: boolean;
12
+ /** Fraction of the segments three's own generators keep (cylinders, spheres, tori, lathes, tubes, extrusions, circles, rings). */
13
+ segmentFraction: number;
14
+ /** Rounding rings of a rounded box (the full build uses 3). */
15
+ roundingRings: number;
16
+ /** Multiplier of the maximum edge length when subdividing a mesh (bigger triangles). */
17
+ subdivisionFactor: number;
18
+ /** A box with an edge under this, or a rounding radius under 1.2 cm, is drawn as a plain 12-triangle box. */
19
+ flatBoxEdge: number;
20
+ /** Fewest segments of a superellipse loft. */
21
+ minLoftSegments: number;
22
+ /** Fraction of a loft's segments. */
23
+ loftSegmentFraction: number;
24
+ /** Fewest stations of a resampled loft. */
25
+ minStations: number;
26
+ /** Fraction of the stations of a resampled loft. */
27
+ stationFraction: number;
28
+ /** Multiplier of the grid cell size of grilles and side grilles. */
29
+ gridFactor: number;
30
+ /** Materials (by name in `kit.materials`) whose meshes are never seen from outside and are left out in light mode. */
31
+ hiddenMaterials: readonly string[];
32
+ }
33
+ declare const defaultLodSettings: LodSettings;
34
+ /** The settings the kit starts with: the defaults, overridden by the options. */
35
+ declare function createLod(options?: Partial<LodSettings>): LodSettings;
36
+ /**
37
+ * A copy of the three.js namespace whose geometry generators take fewer segments while `lod.on` is true (and whose canvas textures come out in
38
+ * sRGB when three has colour management). With `lod.on` false every generator passes its arguments through untouched.
39
+ */
40
+ declare function wrapThreeForLod(TH: any, lod: LodSettings): any;
41
+
42
+ /**
43
+ * Damageable parts: what a bullet, a bat or a crash can hurt on a built vehicle, as boxes. Port of `coletarDanificaveis` and `tipoDaZona`
44
+ * (frota-leve.js 14391-14405), driven by the zones the kit already derives, so it works for any vehicle of any pack.
45
+ */
46
+
47
+ type DamageableMaterial = 'metal' | 'glass' | 'rubber' | 'fuel';
48
+ type DamageableSide = 'center' | 'left' | 'right';
49
+ /** What a zone is, by type: the material it is made of and the part name a game shows. */
50
+ interface DamageableKind {
51
+ material: DamageableMaterial;
52
+ part: string;
53
+ }
54
+ /** Zone type (and, for some, `fxKey` or `sub`) to material and part. A game replaces or adds entries with `kit.damageableKinds`. */
55
+ declare const defaultDamageableKinds: Record<string, DamageableKind>;
56
+
3
57
  var plate = {
4
58
  band: "BRAZIL"
5
59
  };
@@ -487,9 +541,25 @@ interface Plugin {
487
541
  configure?: KitConfiguration;
488
542
  install?(kit: VehicleKit): void;
489
543
  }
544
+ interface BuildOptions {
545
+ /** Build this vehicle in light mode (fewer triangles; interiors tagged `skipLite`). */
546
+ lod?: boolean;
547
+ }
548
+ interface Damageable {
549
+ material: DamageableMaterial;
550
+ /** Id of the zone. */
551
+ zone: string;
552
+ /** `door`, `hood`, `lid`, `bumper`, `window`, `windshield`, `headlight`, `taillight`, `wheel`, `fuel_tank`. */
553
+ part: string;
554
+ side: DamageableSide;
555
+ /** A `THREE.Box3`. */
556
+ box: ThreeObject;
557
+ }
490
558
  interface VehicleKitOptions extends KitConfiguration {
491
559
  /** The three.js namespace (`import * as THREE from 'three'` or `window.THREE`). */
492
560
  THREE: any;
561
+ /** Light mode settings (every number of `defaultLodSettings` can be overridden). */
562
+ lod?: Partial<LodSettings>;
493
563
  /** A registered locale code (`'en'`, `'pt-BR'`), or a partial string table overriding English. Default `'en'`. */
494
564
  locale?: string | PartialLocaleStrings;
495
565
  /** Document used for canvas textures and the UI. Defaults to the global `document`. */
@@ -552,6 +622,10 @@ interface KitInternals {
552
622
  type Builder = (...args: any[]) => any;
553
623
  interface VehicleKit {
554
624
  readonly THREE: any;
625
+ /** The light mode settings (live: change a number and the next build uses it). */
626
+ readonly lod: LodSettings;
627
+ /** Zone type to material and part of `damageables`; add or replace entries. */
628
+ readonly damageableKinds: Record<string, DamageableKind>;
555
629
  /** Translated strings in use. */
556
630
  readonly strings: LocaleStrings;
557
631
  /** Looks up a locale key (`'zones.hood'`) and fills variables. */
@@ -588,7 +662,9 @@ interface VehicleKit {
588
662
  defineFluid(key: string, def: FluidDefinition): FluidDefinition;
589
663
  on(event: string, fn: (...args: any[]) => void): VehicleKit;
590
664
  hook(event: string, ...args: any[]): void;
591
- build(key: string, state?: BuildState, zoneState?: Partial<ZoneState>): VehicleContext;
665
+ build(key: string, state?: BuildState, zoneState?: Partial<ZoneState>, options?: BuildOptions): VehicleContext;
666
+ /** The damageable parts of a built vehicle as boxes (optionally in the frame of `matrix`). */
667
+ damageables(c: VehicleContext, matrix?: ThreeObject): Damageable[];
592
668
  dispose(c: VehicleContext): void;
593
669
  /** Advances particles, fluids, hood, blast and rollover animations by `dt` seconds. */
594
670
  tick(c: VehicleContext, dt: number): void;
@@ -807,6 +883,8 @@ declare function createVehicleDestructible(kit: VehicleKit, vehicleCtx: VehicleC
807
883
 
808
884
  interface VehicleItemOptions {
809
885
  state?: BuildState;
886
+ /** Build in the light mode of the kit (`kit.lod`): fewer segments and no interior, for crowds and for budgets. Default off. */
887
+ lod?: boolean;
810
888
  }
811
889
  interface VehicleItem {
812
890
  /** Add this to the scene: origin at the centre of the footprint on the floor, front facing +z. */
@@ -821,4 +899,4 @@ interface VehicleItem {
821
899
  */
822
900
  declare function buildVehicleItem(kit: VehicleKit, key: string, options?: VehicleItemOptions): VehicleItem;
823
901
 
824
- export { type Band, type BandId, type BandIndex, type BandOverride, type BuildFunction, type BuildState, type DamageMapOptions, type DamageZone, type ExplodeOptions, type FlagEffect, type FluidDefinition, type ImpactOptions, JOINT_RULES, type JointDef, type KitConfiguration, type KitInternals, type KitTexts, LEGACY_STATES, LEGACY_ZONE_IDS, type LocalBox, type LocaleStrings, type OverallHealth, type PartDef, type PartLabel, type PartRole, type PartialLocaleStrings, type Plugin, type ResolvedConfiguration, SEED_SALTS, type ScenarioContext, type ScenarioDefinition, type ScenarioResult, type SplatOptions, type ThreeObject, type ThreeVector, type Translate, type UiHelpers, type VehicleContext, type VehicleDestructible, type VehicleDestructibleOptions, type VehicleItem, type VehicleItemOptions, type VehicleKit, type VehicleKitOptions, type VehicleMeta, type VehicleModel, type VehiclePart, type VehicleSpec, type VehicleStatus, type ZoneDamageEntry, type ZoneEffect, type ZoneState, buildVehicleItem, buildVehicleModel, clamp, createTranslate, createVehicleDestructible, createVehicleKit, format, hash, legacyGlassId, legacyLightId, legacyZoneId, listLocales, registerLegacySeeds, registerLocale, resolveStrings, rng, smooth, strHash };
902
+ export { type Band, type BandId, type BandIndex, type BandOverride, type BuildFunction, type BuildOptions, type BuildState, type DamageMapOptions, type DamageZone, type Damageable, type DamageableKind, type DamageableMaterial, type DamageableSide, type ExplodeOptions, type FlagEffect, type FluidDefinition, type ImpactOptions, JOINT_RULES, type JointDef, type KitConfiguration, type KitInternals, type KitTexts, LEGACY_STATES, LEGACY_ZONE_IDS, type LocalBox, type LocaleStrings, type LodSettings, type OverallHealth, type PartDef, type PartLabel, type PartRole, type PartialLocaleStrings, type Plugin, type ResolvedConfiguration, SEED_SALTS, type ScenarioContext, type ScenarioDefinition, type ScenarioResult, type SplatOptions, type ThreeObject, type ThreeVector, type Translate, type UiHelpers, type VehicleContext, type VehicleDestructible, type VehicleDestructibleOptions, type VehicleItem, type VehicleItemOptions, type VehicleKit, type VehicleKitOptions, type VehicleMeta, type VehicleModel, type VehiclePart, type VehicleSpec, type VehicleStatus, type ZoneDamageEntry, type ZoneEffect, type ZoneState, buildVehicleItem, buildVehicleModel, clamp, createLod, createTranslate, createVehicleDestructible, createVehicleKit, defaultDamageableKinds, defaultLodSettings, format, hash, legacyGlassId, legacyLightId, legacyZoneId, listLocales, registerLegacySeeds, registerLocale, resolveStrings, rng, smooth, strHash, wrapThreeForLod };
@@ -30,9 +30,12 @@ var GameVehicles = (() => {
30
30
  buildVehicleItem: () => buildVehicleItem,
31
31
  buildVehicleModel: () => buildVehicleModel,
32
32
  clamp: () => clamp,
33
+ createLod: () => createLod,
33
34
  createTranslate: () => createTranslate,
34
35
  createVehicleDestructible: () => createVehicleDestructible,
35
36
  createVehicleKit: () => createVehicleKit,
37
+ defaultDamageableKinds: () => defaultDamageableKinds,
38
+ defaultLodSettings: () => defaultLodSettings,
36
39
  format: () => format,
37
40
  hash: () => hash,
38
41
  legacyGlassId: () => legacyGlassId,
@@ -44,7 +47,8 @@ var GameVehicles = (() => {
44
47
  resolveStrings: () => resolveStrings,
45
48
  rng: () => rng,
46
49
  smooth: () => smooth,
47
- strHash: () => strHash
50
+ strHash: () => strHash,
51
+ wrapThreeForLod: () => wrapThreeForLod
48
52
  });
49
53
 
50
54
  // src/locales/en.json
@@ -882,9 +886,11 @@ var GameVehicles = (() => {
882
886
  const V3 = THREE.Vector3;
883
887
  const PI = Math.PI;
884
888
  const I = kit._;
889
+ const lod = kit.lod;
885
890
  function roundedBoxGeometry(w, h, d, r) {
886
891
  r = Math.max(2e-3, Math.min(r, w * 0.45, h * 0.45, d * 0.45));
887
- const nb = 3;
892
+ if (lod.on && (r < 0.012 || Math.max(w, h, d) < lod.flatBoxEdge || Math.min(w, h, d) < 0.08)) return new THREE.BoxGeometry(w, h, d);
893
+ const nb = lod.on ? lod.roundingRings : 3;
888
894
  const n = 2 * nb + 1;
889
895
  const g = new THREE.BoxGeometry(1, 1, 1, n, n, n);
890
896
  const p = g.attributes.position;
@@ -929,6 +935,7 @@ var GameVehicles = (() => {
929
935
  geo.computeVertexNormals();
930
936
  }
931
937
  function subdivide(geo, maxLen) {
938
+ if (lod.on) maxLen = maxLen * lod.subdivisionFactor;
932
939
  const src = geo.index ? geo.toNonIndexed() : geo;
933
940
  const a = src.attributes.position.array;
934
941
  const out = [];
@@ -1658,6 +1665,7 @@ var GameVehicles = (() => {
1658
1665
  const V3 = THREE.Vector3;
1659
1666
  const PI = Math.PI;
1660
1667
  const I = kit._;
1668
+ const lod = kit.lod;
1661
1669
  const { crease } = I;
1662
1670
  function makeWarp(o) {
1663
1671
  function sec(y) {
@@ -1755,6 +1763,7 @@ var GameVehicles = (() => {
1755
1763
  });
1756
1764
  }
1757
1765
  function resample(st, n) {
1766
+ if (lod.on) n = Math.max(lod.minStations, Math.round(n * lod.stationFraction));
1758
1767
  const out = [];
1759
1768
  const L = st.length;
1760
1769
  function P(i) {
@@ -1786,6 +1795,7 @@ var GameVehicles = (() => {
1786
1795
  }
1787
1796
  function smoothLoft(st, o) {
1788
1797
  o = o || {};
1798
+ if (lod.on) o = Object.assign({}, o, { seg: Math.max(lod.minLoftSegments, Math.round((o.seg || 24) * lod.loftSegmentFraction)) });
1789
1799
  if (o.smooth) st = resample(st, o.smooth);
1790
1800
  const seg = o.seg || 24;
1791
1801
  const pos = [];
@@ -9800,16 +9810,167 @@ var GameVehicles = (() => {
9800
9810
  kit.ui = { damageMap, bandButtons, legend, healthBar, scenarioButtons, zoneLabel, bandRange, css, injectStyles };
9801
9811
  }
9802
9812
 
9813
+ // src/lod.ts
9814
+ var defaultLodSettings = {
9815
+ on: false,
9816
+ segmentFraction: 0.5,
9817
+ roundingRings: 1,
9818
+ subdivisionFactor: 2.2,
9819
+ flatBoxEdge: 0.22,
9820
+ minLoftSegments: 14,
9821
+ loftSegmentFraction: 0.45,
9822
+ minStations: 20,
9823
+ stationFraction: 0.55,
9824
+ gridFactor: 2.6,
9825
+ hiddenMaterials: ["seat", "carpet", "headliner", "gauge", "screen", "bay", "hoodLiner", "block", "cover", "radiator", "coolant", "coolantLiq", "washer", "hv", "hose", "leather"]
9826
+ };
9827
+ function createLod(options) {
9828
+ return { ...defaultLodSettings, ...options || {}, on: false };
9829
+ }
9830
+ var fewer = (lod, n, min) => Math.max(min, Math.round(n * lod.segmentFraction));
9831
+ function wrapThreeForLod(TH, lod) {
9832
+ const T = Object.assign({}, TH);
9833
+ if (TH.SRGBColorSpace) {
9834
+ T.CanvasTexture = class extends TH.CanvasTexture {
9835
+ constructor(a, b, c, d, e, f, g, h, i) {
9836
+ super(a, b, c, d, e, f, g, h, i);
9837
+ this.colorSpace = TH.SRGBColorSpace;
9838
+ }
9839
+ };
9840
+ }
9841
+ T.CylinderGeometry = class extends TH.CylinderGeometry {
9842
+ constructor(rt, rb, h, rs, hs, open, ts, tl) {
9843
+ super(rt, rb, h, lod.on && rs != null ? fewer(lod, rs, 6) : rs, lod.on ? 1 : hs, open, ts, tl);
9844
+ }
9845
+ };
9846
+ T.SphereGeometry = class extends TH.SphereGeometry {
9847
+ constructor(r, ws, hs, ps, pl, ts, tl) {
9848
+ super(r, lod.on && ws != null ? fewer(lod, ws, 8) : ws, lod.on && hs != null ? fewer(lod, hs, 5) : hs, ps, pl, ts, tl);
9849
+ }
9850
+ };
9851
+ T.TorusGeometry = class extends TH.TorusGeometry {
9852
+ constructor(r, tube, rs, ts, arc) {
9853
+ super(r, tube, lod.on && rs != null ? fewer(lod, rs, 4) : rs, lod.on && ts != null ? fewer(lod, ts, 8) : ts, arc);
9854
+ }
9855
+ };
9856
+ T.LatheGeometry = class extends TH.LatheGeometry {
9857
+ constructor(pts, seg, a, b) {
9858
+ super(pts, lod.on && seg != null ? fewer(lod, seg, 10) : seg, a, b);
9859
+ }
9860
+ };
9861
+ T.TubeGeometry = class extends TH.TubeGeometry {
9862
+ constructor(path, ts, r, rs, closed) {
9863
+ if (lod.on) {
9864
+ let len = 1;
9865
+ try {
9866
+ len = path.getLength();
9867
+ } catch (e) {
9868
+ }
9869
+ ts = Math.max(6, Math.min(ts == null ? 64 : ts, Math.ceil(len / 0.14)));
9870
+ rs = r < 0.025 ? 3 : Math.max(4, fewer(lod, rs == null ? 8 : rs, 4));
9871
+ }
9872
+ super(path, ts, r, rs, closed);
9873
+ }
9874
+ };
9875
+ T.ExtrudeGeometry = class extends TH.ExtrudeGeometry {
9876
+ constructor(shape, o) {
9877
+ if (lod.on && o) {
9878
+ o = Object.assign({}, o);
9879
+ if (o.curveSegments) o.curveSegments = fewer(lod, o.curveSegments, 5);
9880
+ if (o.bevelSegments) o.bevelSegments = Math.max(1, Math.round(o.bevelSegments * 0.5));
9881
+ }
9882
+ super(shape, o);
9883
+ }
9884
+ };
9885
+ T.CircleGeometry = class extends TH.CircleGeometry {
9886
+ constructor(r, seg, a, b) {
9887
+ super(r, lod.on && seg != null ? fewer(lod, seg, 8) : seg, a, b);
9888
+ }
9889
+ };
9890
+ T.RingGeometry = class extends TH.RingGeometry {
9891
+ constructor(a, b, ts, ps, c, d) {
9892
+ super(a, b, lod.on && ts != null ? fewer(lod, ts, 8) : ts, ps, c, d);
9893
+ }
9894
+ };
9895
+ return T;
9896
+ }
9897
+ var INTERIOR_FUNCTIONS = ["interior", "engineBay", "seat", "dashboard", "steeringWheel", "yoke", "busRows"];
9898
+ function installLod(kit) {
9899
+ const lod = kit.lod;
9900
+ const meshesOf = (c) => {
9901
+ const set = /* @__PURE__ */ new Set();
9902
+ c.vehicle.traverse((o) => {
9903
+ if (o.isMesh) set.add(o);
9904
+ });
9905
+ return set;
9906
+ };
9907
+ for (const name of INTERIOR_FUNCTIONS) {
9908
+ const original = kit[name];
9909
+ if (typeof original !== "function") continue;
9910
+ kit[name] = function(...args) {
9911
+ const c = args[0];
9912
+ if (!lod.on || !c || !c.vehicle) return original.apply(this, args);
9913
+ const before = meshesOf(c);
9914
+ const result = original.apply(this, args);
9915
+ c.vehicle.traverse((o) => {
9916
+ if (o.isMesh && !before.has(o)) o.userData.skipLite = true;
9917
+ });
9918
+ return result;
9919
+ };
9920
+ }
9921
+ kit.lodHiddenMaterials = function() {
9922
+ const materials = kit.materials;
9923
+ return new Set(lod.hiddenMaterials.map((name) => materials[name]).filter(Boolean));
9924
+ };
9925
+ }
9926
+
9927
+ // src/damageables.ts
9928
+ var defaultDamageableKinds = {
9929
+ door: { material: "metal", part: "door" },
9930
+ hood: { material: "metal", part: "hood" },
9931
+ lid: { material: "metal", part: "lid" },
9932
+ bumper: { material: "metal", part: "bumper" },
9933
+ glass: { material: "glass", part: "window" },
9934
+ "glass:windshield": { material: "glass", part: "windshield" },
9935
+ light: { material: "glass", part: "headlight" },
9936
+ "light:taillight": { material: "glass", part: "taillight" },
9937
+ wheel: { material: "rubber", part: "wheel" },
9938
+ "internal:fuel_tank": { material: "fuel", part: "fuel_tank" }
9939
+ };
9940
+ function installDamageables(kit) {
9941
+ const THREE = kit.THREE;
9942
+ kit.damageableKinds = { ...defaultDamageableKinds };
9943
+ const kindOf2 = (zone) => {
9944
+ const kinds = kit.damageableKinds;
9945
+ if (zone.type === "internal") return zone.sub ? kinds[`internal:${zone.sub}`] || null : null;
9946
+ return kinds[`${zone.type}:${zone.fxKey}`] || kinds[zone.type] || null;
9947
+ };
9948
+ kit.damageables = function(c, matrix) {
9949
+ const out = [];
9950
+ for (const zone of c.zones || []) {
9951
+ const kind = kindOf2(zone);
9952
+ if (!kind || !zone.box) continue;
9953
+ const b = zone.box;
9954
+ const box = new THREE.Box3(new THREE.Vector3(b.x0, b.y0, b.z0), new THREE.Vector3(b.x1, b.y1, b.z1));
9955
+ if (matrix) box.applyMatrix4(matrix);
9956
+ out.push({ material: kind.material, zone: zone.id, part: kind.part, side: zone.side === 0 ? "center" : zone.side < 0 ? "left" : "right", box });
9957
+ }
9958
+ return out;
9959
+ };
9960
+ }
9961
+
9803
9962
  // src/kit.ts
9804
9963
  function createVehicleKit(options) {
9805
9964
  const opts = options || {};
9806
- const THREE = opts.THREE;
9807
- if (!THREE || !THREE.Vector3) throw new Error("createVehicleKit: options.THREE (the three.js namespace) is required");
9965
+ if (!opts.THREE || !opts.THREE.Vector3) throw new Error("createVehicleKit: options.THREE (the three.js namespace) is required");
9966
+ const lod = createLod(opts.lod);
9967
+ const THREE = wrapThreeForLod(opts.THREE, lod);
9808
9968
  const strings = resolveStrings(opts.locale);
9809
9969
  const t = createTranslate(strings);
9810
9970
  const doc = opts.document || (typeof document !== "undefined" ? document : void 0);
9811
9971
  const kit = {
9812
9972
  THREE,
9973
+ lod,
9813
9974
  V3: THREE.Vector3,
9814
9975
  PI: Math.PI,
9815
9976
  document: doc,
@@ -9881,6 +10042,8 @@ var GameVehicles = (() => {
9881
10042
  installZoneApply(kit);
9882
10043
  installScenarios(kit);
9883
10044
  installUi(kit);
10045
+ installLod(kit);
10046
+ installDamageables(kit);
9884
10047
  const I = kit._;
9885
10048
  const HOOKS = {};
9886
10049
  kit.on = function(ev, fn) {
@@ -9975,9 +10138,18 @@ var GameVehicles = (() => {
9975
10138
  }
9976
10139
  }
9977
10140
  kit.defaultDamage = defaultDamage;
9978
- kit.build = function(key, state, zoneState) {
10141
+ kit.build = function(key, state, zoneState, options2) {
9979
10142
  const spec = kit.find(key);
9980
10143
  if (!spec) throw new Error("Unknown vehicle: " + key);
10144
+ const lodBefore = lod.on;
10145
+ if (options2 && options2.lod != null) lod.on = !!options2.lod;
10146
+ try {
10147
+ return buildVehicle(spec, key, state, zoneState);
10148
+ } finally {
10149
+ lod.on = lodBefore;
10150
+ }
10151
+ };
10152
+ function buildVehicle(spec, key, state, zoneState) {
9981
10153
  const st = state || "intact";
9982
10154
  const seedKey = spec.seedKey || key;
9983
10155
  const c = new kit.BuildContext(st, strHash(seedKey + (LEGACY_STATES[st] || st)));
@@ -10026,7 +10198,7 @@ var GameVehicles = (() => {
10026
10198
  if (o.isMesh && !(o.material && o.material.transparent)) o.receiveShadow = true;
10027
10199
  });
10028
10200
  return c;
10029
- };
10201
+ }
10030
10202
  kit.dispose = function(c) {
10031
10203
  const shared = Object.values(I.PARTICLE_GEOMETRIES);
10032
10204
  c.root.traverse(function(o) {
@@ -10043,8 +10215,9 @@ var GameVehicles = (() => {
10043
10215
  assignDeep(strings, resolveStrings(opts.locale));
10044
10216
  return kit;
10045
10217
  };
10046
- const { THREE: _three, locale: _locale, document: _document, plugins, ...config } = opts;
10218
+ const { THREE: _three, lod: _lod, locale: _locale, document: _document, plugins, ...config } = opts;
10047
10219
  void _three;
10220
+ void _lod;
10048
10221
  void _locale;
10049
10222
  void _document;
10050
10223
  kit.configure(config);
@@ -11998,7 +12171,7 @@ var GameVehicles = (() => {
11998
12171
  // src/destructible/item.ts
11999
12172
  function buildVehicleItem(kit, key, options = {}) {
12000
12173
  const THREE = kit.THREE;
12001
- const vehicle = kit.build(key, options.state ?? "intact");
12174
+ const vehicle = options.lod ? kit.build(key, options.state ?? "intact", void 0, { lod: true }) : kit.build(key, options.state ?? "intact");
12002
12175
  const m = vehicle.meta;
12003
12176
  const root = new THREE.Group();
12004
12177
  root.name = key;