@adatechnology/game-contracts 0.23.0 → 0.25.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.d.ts +104 -5
- package/dist/index.global.js +86 -14
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +86 -14
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -92,6 +92,8 @@ interface PartSpec {
|
|
|
92
92
|
radius: number;
|
|
93
93
|
/** Inside this radius (metres) the blast is lethal to a body; from here to `radius` it only hurts, less with distance. Without it a body takes the energy falling off over `radius`. */
|
|
94
94
|
lethalRadius?: number;
|
|
95
|
+
/** Kilograms of TNT equivalent of the burst: the blast wave that pushes bodies is read from it (`knockOf`). */
|
|
96
|
+
tnt?: number;
|
|
95
97
|
atC?: number;
|
|
96
98
|
/**
|
|
97
99
|
* Chain reaction: what sets the part off before it is destroyed and the seconds from that to the blast (a number, or `[min, max]` drawn
|
|
@@ -757,6 +759,7 @@ type DestructionEvent = (EventBase & {
|
|
|
757
759
|
energy: number;
|
|
758
760
|
radius: number;
|
|
759
761
|
lethalRadius?: number;
|
|
762
|
+
tnt?: number;
|
|
760
763
|
effect?: string;
|
|
761
764
|
})
|
|
762
765
|
/** An explosive part was set off by a bullet, fire or a nearby blast and will explode `delay` seconds from now (`explodes.chain`). */
|
|
@@ -832,6 +835,8 @@ type DestructionEvent = (EventBase & {
|
|
|
832
835
|
* One unit of a wall of units (`PartSpec.units`: a brick, a block) came out under shots or blows: `center` in world space, `size` in the part's own
|
|
833
836
|
* axes and `rotation` the part's world rotation (the box of the unit that left), `fragments` the unit itself. The part stays: draw the gap, do not hide it.
|
|
834
837
|
* With `torn`, nothing left the part but what a blow tore off its face (splinters of wood, lumps of MDF): the hole and the marks around it stay drawn.
|
|
838
|
+
* With `units`, a blast knocked many units out at once: each one's box (`center` in world space, `size` in the part's axes, turned by `rotation`), and
|
|
839
|
+
* `center` and `size` are the box around them all.
|
|
835
840
|
*/
|
|
836
841
|
| (EventBase & {
|
|
837
842
|
type: 'chip';
|
|
@@ -841,6 +846,10 @@ type DestructionEvent = (EventBase & {
|
|
|
841
846
|
rotation: Quat;
|
|
842
847
|
fragments: readonly Fragment[];
|
|
843
848
|
torn?: true;
|
|
849
|
+
units?: readonly {
|
|
850
|
+
center: Vec3;
|
|
851
|
+
size: Vec3;
|
|
852
|
+
}[];
|
|
844
853
|
})
|
|
845
854
|
/** Rebar of a reinforced part is bare: segments in world space. Empty `bars` means the cage is gone. */
|
|
846
855
|
| (EventBase & {
|
|
@@ -969,6 +978,13 @@ interface BlastSource {
|
|
|
969
978
|
readonly energy: number;
|
|
970
979
|
readonly radius: number;
|
|
971
980
|
readonly reach?: number;
|
|
981
|
+
/**
|
|
982
|
+
* Kilograms of TNT equivalent of the charge. With it a body is pushed by the blast wave itself (`blast-impulse`), and the shove of loose items keeps this module's rule; without it the body
|
|
983
|
+
* takes the charge from `energy` by `BlastImpulseOptions.tntPerJoule`.
|
|
984
|
+
*/
|
|
985
|
+
readonly tnt?: number;
|
|
986
|
+
/** Inside this radius (metres) the blast is lethal: a body there that the blast reaches (not behind cover) goes down, wounded, wherever the wave pushed it. */
|
|
987
|
+
readonly lethalRadius?: number;
|
|
972
988
|
}
|
|
973
989
|
/** What a blast does to one body: how fast it leaves (m/s), the unit direction it leaves in, and how far from the centre it was. */
|
|
974
990
|
interface BlastShove {
|
|
@@ -980,7 +996,7 @@ interface BlastShove {
|
|
|
980
996
|
}
|
|
981
997
|
/**
|
|
982
998
|
* The shove a blast gives to a body of `mass` kg whose centre is at `position`: away from the centre, lifted a little, with the speed
|
|
983
|
-
* `min(maxSpeed, sqrt(2 * energy *
|
|
999
|
+
* `sqrt(reach) * min(maxSpeed, sqrt(2 * energy * coupling / mass)) * (1 - distance / radius) ^ 2`. Undefined when the body is outside the radius or the speed is under `minSpeed`.
|
|
984
1000
|
* The same rule moves the loose items and furniture of the test room and the people of the characters module, so a game that tunes the options tunes all of them.
|
|
985
1001
|
*/
|
|
986
1002
|
declare function blastShove(blast: BlastSource, target: {
|
|
@@ -988,10 +1004,45 @@ declare function blastShove(blast: BlastSource, target: {
|
|
|
988
1004
|
readonly mass: number;
|
|
989
1005
|
}, options?: BlastShoveOptions): BlastShove | undefined;
|
|
990
1006
|
|
|
1007
|
+
/**
|
|
1008
|
+
* The push a blast gives a standing body, from the physics of the blast wave and not from a game coupling: the impulse of the wave per square metre at a distance from a charge of
|
|
1009
|
+
* `tnt` kg of TNT equivalent (Kinney and Graham's fit of the side-on impulse, scaled by the cube root of the charge), reflected on the body, over the area the body shows the wave,
|
|
1010
|
+
* divided by its mass. A hand grenade at 3 m gives a person a few tenths of a metre per second; what floors that person is the fragments, not the wave. A big charge close throws.
|
|
1011
|
+
*/
|
|
1012
|
+
/** The numbers of the body a blast wave pushes. All have a default for a standing adult. */
|
|
1013
|
+
interface BlastImpulseOptions {
|
|
1014
|
+
/** Square metres of the body the wave meets: about 1.75 m tall by 0.4 m wide (default 0.7). */
|
|
1015
|
+
readonly bodyArea?: number;
|
|
1016
|
+
/** How much of the push goes up: the direction is `(away, lift)` normalised (default 0.15: the wave runs along the ground). */
|
|
1017
|
+
readonly lift?: number;
|
|
1018
|
+
/** Below this speed (m/s) the body does not move (default 0.3). */
|
|
1019
|
+
readonly minSpeed?: number;
|
|
1020
|
+
/**
|
|
1021
|
+
* Kilograms of TNT per joule of the blast `energy`, for a blast that does not say its charge (`BlastSource.tnt`). Default 0.24 / 200000: the arsenal's energy scale, where the M67 (180 g
|
|
1022
|
+
* of Composition B, 0.24 kg of TNT) is 200 kJ. It is a game equivalence for blasts without a charge, not a physical constant.
|
|
1023
|
+
*/
|
|
1024
|
+
readonly tntPerJoule?: number;
|
|
1025
|
+
}
|
|
1026
|
+
declare const DEFAULT_BLAST_IMPULSE: Readonly<Required<BlastImpulseOptions>>;
|
|
1027
|
+
/**
|
|
1028
|
+
* Side-on (incident) specific impulse of the wave, in Pa·s, at `distance` metres from `tnt` kg of TNT in free air: Kinney and Graham, "Explosive Shocks in Air" (1985),
|
|
1029
|
+
* `I/W^(1/3) = 0.067 sqrt(1 + (Z/0.23)^4) / (Z^2 (1 + (Z/1.55)^3)^(1/3))` bar·ms per kg^(1/3), with the scaled distance `Z = R / W^(1/3)`.
|
|
1030
|
+
*/
|
|
1031
|
+
declare function sideOnImpulse(tnt: number, distance: number): number;
|
|
1032
|
+
/**
|
|
1033
|
+
* The impulse per square metre a body facing the wave takes, Pa·s: the side-on impulse reflected. The reflection doubles a weak wave and grows up to about six times close to the charge,
|
|
1034
|
+
* where the wave is strong (the ratio of reflected to side-on impulse of the Kingery-Bulmash charts, fitted as `2 + 4 / (1 + Z^2)`).
|
|
1035
|
+
*/
|
|
1036
|
+
declare function bodyImpulse(tnt: number, distance: number): number;
|
|
1037
|
+
/** The speed (m/s) a blast wave gives a free body of `mass` kg at `distance` metres from `tnt` kg of TNT, `reach` (0..1) of it getting through what stands in the way. */
|
|
1038
|
+
declare function blastBodySpeed(tnt: number, distance: number, mass: number, reach?: number, options?: BlastImpulseOptions): number;
|
|
1039
|
+
|
|
991
1040
|
/** From this speed (m/s) a blast takes a standing body off its feet. Below it the body is only pushed. */
|
|
992
1041
|
declare const KNOCK_DOWN_SPEED = 2.5;
|
|
993
1042
|
/** The angle of a body lying where it fell (the same tilt a dead body takes). */
|
|
994
1043
|
declare const KNOCKED_DOWN_ANGLE = 1.35;
|
|
1044
|
+
/** The share of the blast that has to get through for its fragments to reach a body: behind cover that stops half of it the fragments stop too. */
|
|
1045
|
+
declare const FRAGMENT_COVER = 0.5;
|
|
995
1046
|
/** Height of the chest above the feet: where the blast takes the body. */
|
|
996
1047
|
declare const KNOCK_CHEST = 1.1;
|
|
997
1048
|
/** What a blast is doing to one body: its velocity (m/s), whether it is in the air, and how far down it is (0 on its feet, 1 lying). */
|
|
@@ -1004,14 +1055,23 @@ interface Knock {
|
|
|
1004
1055
|
lieLeft: number;
|
|
1005
1056
|
/** Knocked off its feet by this blast. */
|
|
1006
1057
|
down: boolean;
|
|
1058
|
+
/** Floored by its wounds: inside the lethal radius and not behind cover. It lies longer and falls where it stood. */
|
|
1059
|
+
wounded?: boolean;
|
|
1060
|
+
/** Seconds of stun the blast gave the body: dizziness and ringing ears. */
|
|
1061
|
+
stunSeconds?: number;
|
|
1062
|
+
/** The horizontal unit direction away from the blast, even when the push is too weak to move the body: the way it falls. */
|
|
1063
|
+
away?: Vec3;
|
|
1007
1064
|
}
|
|
1008
1065
|
/** The mass of a body in kg from its height (m) and its build (1 = average): 70 kg at 1.75 m. */
|
|
1009
1066
|
declare const bodyMass: (height: number, build?: number) => number;
|
|
1010
1067
|
/**
|
|
1011
|
-
* What a blast does to a body standing at `feet
|
|
1012
|
-
*
|
|
1068
|
+
* What a blast does to a body standing at `feet`, of `mass` kg. Undefined when the blast does not reach it or does nothing to it.
|
|
1069
|
+
*
|
|
1070
|
+
* The body is pushed by the blast wave (`blastBodySpeed`, from the charge `blast.tnt`, or from `energy` by `tntPerJoule`), taken at the chest and cut by `reach`, the share that got through
|
|
1071
|
+
* cover. It is floored when that push is `KNOCK_DOWN_SPEED` or more, or when it stands inside `lethalRadius` with the blast reaching it (the fragments and the overpressure fell it where it
|
|
1072
|
+
* stands). It is stunned for a while inside the radius. `options` are the shove numbers of the host's loose items; only their `minSpeed` applies to a body.
|
|
1013
1073
|
*/
|
|
1014
|
-
declare function knockOf(blast: BlastSource, feet: Vec3, mass: number, options?: BlastShoveOptions): Knock | undefined;
|
|
1074
|
+
declare function knockOf(blast: BlastSource, feet: Vec3, mass: number, options?: BlastShoveOptions, impulse?: BlastImpulseOptions): Knock | undefined;
|
|
1015
1075
|
/**
|
|
1016
1076
|
* Moves a body one step: it slides on the ground and slows, falls when it was knocked down, lies a while and gets up (a dead body stays down). Moves `position` in place; returns true when the
|
|
1017
1077
|
* body is on its feet and still, and the knock can be dropped.
|
|
@@ -1021,6 +1081,17 @@ declare function stepKnock(knock: Knock, position: {
|
|
|
1021
1081
|
y: number;
|
|
1022
1082
|
z: number;
|
|
1023
1083
|
}, dt: number, groundAt: (x: number, z: number) => number, alive: boolean): boolean;
|
|
1084
|
+
/**
|
|
1085
|
+
* Throws a body at `velocity` (m/s, world): an occupant leaving a car through the glass, a pedestrian run over. The module that animates the body
|
|
1086
|
+
* takes it on its next frame (`takeLaunch`) and moves it as it moves a body a blast knocked down: flying, landing, sliding, lying, getting up.
|
|
1087
|
+
*/
|
|
1088
|
+
declare function launchBody(root: {
|
|
1089
|
+
userData: Record<string, unknown>;
|
|
1090
|
+
}, velocity: Vec3): void;
|
|
1091
|
+
/** The throw `launchBody` left on the root, as a knock (knocked down, in the air), once; undefined when nothing threw it. */
|
|
1092
|
+
declare function takeLaunch(root: {
|
|
1093
|
+
userData: Record<string, unknown>;
|
|
1094
|
+
}): Knock | undefined;
|
|
1024
1095
|
|
|
1025
1096
|
interface CostOptions {
|
|
1026
1097
|
/** Reads of `state()` and of `describe()` to time. Default 10 000. */
|
|
@@ -1496,6 +1567,16 @@ interface HandTargets {
|
|
|
1496
1567
|
}
|
|
1497
1568
|
/** Read every frame by whoever draws the arms; answers null while nothing is held. */
|
|
1498
1569
|
type HandTargetSource = () => HandTargets | null;
|
|
1570
|
+
/** The muzzle of the tool in the hands as it is drawn now (world space): where a shot's flash and tracer leave, and which way the barrel points. */
|
|
1571
|
+
interface MuzzlePose {
|
|
1572
|
+
readonly position: Vec3;
|
|
1573
|
+
/** Unit vector along the barrel, out of the muzzle. */
|
|
1574
|
+
readonly direction: Vec3;
|
|
1575
|
+
/** The module draws the muzzle flash itself: the host draws none of its own. */
|
|
1576
|
+
readonly drawsFlash: boolean;
|
|
1577
|
+
}
|
|
1578
|
+
/** Read by the host at each shot; null while the tool in the hands has no muzzle (a knife, a bare hand). */
|
|
1579
|
+
type MuzzleSource = () => MuzzlePose | null;
|
|
1499
1580
|
|
|
1500
1581
|
/** How a hand turns something round in strokes (a screw cap, a tap handle, a knob): what `twistStroke` answers for one moment of the turning. */
|
|
1501
1582
|
interface TwistStroke {
|
|
@@ -2143,6 +2224,8 @@ interface AreaPlacement {
|
|
|
2143
2224
|
interface GroundZone {
|
|
2144
2225
|
readonly rect: readonly [number, number, number, number];
|
|
2145
2226
|
readonly surface: string;
|
|
2227
|
+
/** Sign a renderer lays on the front edge of the zone (the side of +z). */
|
|
2228
|
+
readonly label?: string;
|
|
2146
2229
|
}
|
|
2147
2230
|
/** What the floor is made of. `surface` is a ground profile id (`lawn`, `road`, `concrete_slab`, `tile_floor`...); a host that does not know it uses its default. */
|
|
2148
2231
|
interface GroundLayout {
|
|
@@ -2290,6 +2373,10 @@ type HostEvent =
|
|
|
2290
2373
|
radius: number;
|
|
2291
2374
|
cause: string;
|
|
2292
2375
|
explosive?: string;
|
|
2376
|
+
/** Kilograms of TNT equivalent of the charge, when the explosive says it: the blast wave that pushes bodies is read from it (`knockOf`). */
|
|
2377
|
+
tnt?: number;
|
|
2378
|
+
/** Inside this radius (metres) the blast is lethal to a body it reaches. */
|
|
2379
|
+
lethalRadius?: number;
|
|
2293
2380
|
}
|
|
2294
2381
|
/** The player crouched or stood up, or the camera mode changed; read the new state with `host.player()`. */
|
|
2295
2382
|
| {
|
|
@@ -2499,6 +2586,11 @@ interface ModuleHost {
|
|
|
2499
2586
|
* frame hooks have run, and puts the hands there. Pass null (or call the returned function) to let go. A host without arms leaves it out.
|
|
2500
2587
|
*/
|
|
2501
2588
|
setHandTargets?(source: HandTargetSource | null): () => void;
|
|
2589
|
+
/**
|
|
2590
|
+
* Lends the host the muzzle of the tool the module draws in the hands: the host reads `source` at each shot and puts the tracer (and, unless the module draws one, the flash) there, at the
|
|
2591
|
+
* muzzle of the model and not at a guess in front of the eye. Pass null (or call the returned function) to let go. A host that draws no shot effects leaves it out.
|
|
2592
|
+
*/
|
|
2593
|
+
setMuzzleSource?(source: MuzzleSource | null): () => void;
|
|
2502
2594
|
/**
|
|
2503
2595
|
* Where the player's body holds a tool now (world space), in every view (the weapon is the body's own): `position` is the pocket of the right shoulder a stock rests on, `quaternion` turns
|
|
2504
2596
|
* to the aim (-z the aim, x right, y up, as a camera). A module draws the tool there at its real size. Null for a host with no body (the module puts the same pocket under the camera's eye);
|
|
@@ -2522,6 +2614,13 @@ interface ModuleHost {
|
|
|
2522
2614
|
* that keeps its camera to itself leaves it out.
|
|
2523
2615
|
*/
|
|
2524
2616
|
setViewCamera?(camera: unknown | null): void;
|
|
2617
|
+
/**
|
|
2618
|
+
* Holds the walking player where it stands (true) or lets it walk again (false): the movement keys then belong to the module (a vehicle the player drives). Mouse look,
|
|
2619
|
+
* the panels and the room's other keys keep working. A host without a walking player leaves it out.
|
|
2620
|
+
*/
|
|
2621
|
+
holdPlayer?(held: boolean): void;
|
|
2622
|
+
/** True while a module holds the player (`holdPlayer(true)`): the keys then belong to that module, and another module's own keys (a weapon's accessories) stay out of its way. */
|
|
2623
|
+
playerHeld?(): boolean;
|
|
2525
2624
|
/** Lent only to a module that declares controls, layers or metrics. */
|
|
2526
2625
|
bench?: ModuleBench;
|
|
2527
2626
|
/** The host's shared sound engine; a module that makes sound uses it when lent and stays silent (or brings its own) when not. */
|
|
@@ -2807,4 +2906,4 @@ declare function footprintBlocker(object: FootprintObject | (() => FootprintObje
|
|
|
2807
2906
|
/** @deprecated Import it from `@adatechnology/game-contracts/testing`. */
|
|
2808
2907
|
declare const resetWarnOnce: () => void;
|
|
2809
2908
|
|
|
2810
|
-
export { type ActionControl, type AnimationClipSpec, type AnimationEventSpec, type AnimationKey, type AnimationPose, type AreaPlacement, type AudioListener, type AudioSink, BLOW_IDS, BODY_FOLEY_IDS, BODY_SOUND_IDS, type BallisticExtras, type BenchChange, type BenchDeclaration, type BenchReport, type BenchSheet, type BlastOptions, type BlastReport, type BlastShove, type BlastShoveOptions, type BlastSource, type BlowId, type BlowTarget, type BodyFoleyId, type BodyRegion, type BodySlot, type BodySoundId, type BooleanControl, type BusyOptions, type BusySink, type BusyTask, type CategorizedOptions, type CategorizedReport, type CategoryDef, type CategoryOptions, type CategoryRegistry, type ChainDelay, type CheckOptions, type CheckSpecOptions, type ChoiceControl, type ChoiceOption, type ConfinementOptions, type ContainerSpec, type ContractChecker, type ContractContext, type ControlPatch, type ControlValue, type CostOptions, type Crack, DEFAULT_BLAST_SHOVE, DEFAULT_ENVIRONMENT, DEFAULT_IGNITION_RULES, DEFAULT_SURFACE, DEFERRED_PRIORITY, DEFERRED_QUEUE_ID, type DamageStage, type DamageType, type DebrisKind, type DeepPartial, type DeferredQueue, type DeferredQueueOptions, type DeferredQueueReport, type Dent, type DestructibleImpl, type DestructibleSpec, type DestructionEvent, type DestructionEventType, type EffectHandle, type EffectRequest, type EffectSink, type Enclosure, type EnclosureBox, type EnvironmentBus, type EnvironmentKey, type EnvironmentState, type ExplosionChain, FOOTSTEP_SOUND_IDS, FRAME_PHASES, type FluidKind, type Footprint, type FootprintObject, type FootstepSoundId, type FractureStyle, type Fragment, type FragmentHitOptions, type FragmentMark, type FrameOptions, type FramePhase, GAIT_IDS, type GaitId, type GroundLayout, type GroundZone, HEAVY_LANDING_SPEED, type HandPose, type HandTargetSource, type HandTargets, type Hit, type HitIgnition, type HitResult, type Hole, type HostEvent, type HostGraphics, type HostReach, type HostTool, type HostToolAttachment, IMPACT_CONTRACT, type IgnitionRules, type ImpactContract, type ItemAnimationContract, type ItemSeat, type ItemSounds, type ItemUseDef, type JointKind, type JointSpec, type JointState, KIT_ORIGIN_KEY, KNOCKED_DOWN_ANGLE, KNOCK_CHEST, KNOCK_DOWN_SPEED, type KitOrigin, type Knock, LANDING_IDS, LAND_SOUND_IDS, type LandSoundId, type LandingId, type LiquidId, type LoopHandle, MATERIAL_SURFACES, MISSING_BITS, type MaterialId, type ModuleArea, type ModuleBench, type ModuleControl, type ModuleHost, type ModuleItemFluid, type ModuleItemSeal, type ModuleLayer, type ModuleMetric, type ModuleScenario, type ModuleView, type NumberControl, type ObjectState, type PartBreach, type PartShape, type PartSpec, type PartState, type PartStatus, type PartUnits, type PileSpec, type PlayerState, type Quat, type RayHit, type Reinforcement, STAGE_EVENT, SURFACE_IDS, SWING_LEAD_SECONDS, type SealBlock, type SealSpec, type SealState, type SegmentKind, type ShelterOptions, type Shot, type SoilLayer, type SoilProfile, type SoilState, type SoundHandle, type SoundRequest, type SpecReport, type StructureRole, type SurfaceId, type SurfaceLayer, type SurfaceRay, type SurfaceRayHit, TOOL_CLIP, TWIST_LIFT, type TensionRebar, type TestableItem, type TestableModule, type Thumbnail, type ToolAnimationStep, type ToolAnimator, type ToolClipId, type ToolClipPlayer, type ToolClipPlayerOptions, type ToolClipSet, type ToolCommand, type ToolCommandResult, type ToolKind, type ToolRig, type TunedMassDamper, type TwistOptions, type TwistStroke, type UnmarkedDrawing, type Use, type Vec3, type WarmUpProbes, type WindExposure, type WindState, applyPatches, blastShove, bodyMass, checkAnimation, checkBench, checkCategorized, checkDeferredQueue, checkDestructible, checkHit, checkSpec, checkToolClips, createEnvironmentBus, createToolClipPlayer, deepMerge, defineCategories, fillFactor, footprintBlocker, footstepSoundId, hitSoundId, ignitionChance, isSurfaceId, kitOriginOf, knockOf, landSoundId, leadClipEvents, markKitOrigin, mergeById, removeIds, resetWarnOnce, resolveEntry, resolveIgnitionRules, sampleClip, scaleClip, sealBlock, sealOpener, shotExtras, shotToHit, sparkTargetFactor, stepKnock, surfaceOfMaterial, swingSoundId, toolAnimationStep, twistStroke, unmarkedDrawings, useToHit };
|
|
2909
|
+
export { type ActionControl, type AnimationClipSpec, type AnimationEventSpec, type AnimationKey, type AnimationPose, type AreaPlacement, type AudioListener, type AudioSink, BLOW_IDS, BODY_FOLEY_IDS, BODY_SOUND_IDS, type BallisticExtras, type BenchChange, type BenchDeclaration, type BenchReport, type BenchSheet, type BlastImpulseOptions, type BlastOptions, type BlastReport, type BlastShove, type BlastShoveOptions, type BlastSource, type BlowId, type BlowTarget, type BodyFoleyId, type BodyRegion, type BodySlot, type BodySoundId, type BooleanControl, type BusyOptions, type BusySink, type BusyTask, type CategorizedOptions, type CategorizedReport, type CategoryDef, type CategoryOptions, type CategoryRegistry, type ChainDelay, type CheckOptions, type CheckSpecOptions, type ChoiceControl, type ChoiceOption, type ConfinementOptions, type ContainerSpec, type ContractChecker, type ContractContext, type ControlPatch, type ControlValue, type CostOptions, type Crack, DEFAULT_BLAST_IMPULSE, DEFAULT_BLAST_SHOVE, DEFAULT_ENVIRONMENT, DEFAULT_IGNITION_RULES, DEFAULT_SURFACE, DEFERRED_PRIORITY, DEFERRED_QUEUE_ID, type DamageStage, type DamageType, type DebrisKind, type DeepPartial, type DeferredQueue, type DeferredQueueOptions, type DeferredQueueReport, type Dent, type DestructibleImpl, type DestructibleSpec, type DestructionEvent, type DestructionEventType, type EffectHandle, type EffectRequest, type EffectSink, type Enclosure, type EnclosureBox, type EnvironmentBus, type EnvironmentKey, type EnvironmentState, type ExplosionChain, FOOTSTEP_SOUND_IDS, FRAGMENT_COVER, FRAME_PHASES, type FluidKind, type Footprint, type FootprintObject, type FootstepSoundId, type FractureStyle, type Fragment, type FragmentHitOptions, type FragmentMark, type FrameOptions, type FramePhase, GAIT_IDS, type GaitId, type GroundLayout, type GroundZone, HEAVY_LANDING_SPEED, type HandPose, type HandTargetSource, type HandTargets, type Hit, type HitIgnition, type HitResult, type Hole, type HostEvent, type HostGraphics, type HostReach, type HostTool, type HostToolAttachment, IMPACT_CONTRACT, type IgnitionRules, type ImpactContract, type ItemAnimationContract, type ItemSeat, type ItemSounds, type ItemUseDef, type JointKind, type JointSpec, type JointState, KIT_ORIGIN_KEY, KNOCKED_DOWN_ANGLE, KNOCK_CHEST, KNOCK_DOWN_SPEED, type KitOrigin, type Knock, LANDING_IDS, LAND_SOUND_IDS, type LandSoundId, type LandingId, type LiquidId, type LoopHandle, MATERIAL_SURFACES, MISSING_BITS, type MaterialId, type ModuleArea, type ModuleBench, type ModuleControl, type ModuleHost, type ModuleItemFluid, type ModuleItemSeal, type ModuleLayer, type ModuleMetric, type ModuleScenario, type ModuleView, type MuzzlePose, type MuzzleSource, type NumberControl, type ObjectState, type PartBreach, type PartShape, type PartSpec, type PartState, type PartStatus, type PartUnits, type PileSpec, type PlayerState, type Quat, type RayHit, type Reinforcement, STAGE_EVENT, SURFACE_IDS, SWING_LEAD_SECONDS, type SealBlock, type SealSpec, type SealState, type SegmentKind, type ShelterOptions, type Shot, type SoilLayer, type SoilProfile, type SoilState, type SoundHandle, type SoundRequest, type SpecReport, type StructureRole, type SurfaceId, type SurfaceLayer, type SurfaceRay, type SurfaceRayHit, TOOL_CLIP, TWIST_LIFT, type TensionRebar, type TestableItem, type TestableModule, type Thumbnail, type ToolAnimationStep, type ToolAnimator, type ToolClipId, type ToolClipPlayer, type ToolClipPlayerOptions, type ToolClipSet, type ToolCommand, type ToolCommandResult, type ToolKind, type ToolRig, type TunedMassDamper, type TwistOptions, type TwistStroke, type UnmarkedDrawing, type Use, type Vec3, type WarmUpProbes, type WindExposure, type WindState, applyPatches, blastBodySpeed, blastShove, bodyImpulse, bodyMass, checkAnimation, checkBench, checkCategorized, checkDeferredQueue, checkDestructible, checkHit, checkSpec, checkToolClips, createEnvironmentBus, createToolClipPlayer, deepMerge, defineCategories, fillFactor, footprintBlocker, footstepSoundId, hitSoundId, ignitionChance, isSurfaceId, kitOriginOf, knockOf, landSoundId, launchBody, leadClipEvents, markKitOrigin, mergeById, removeIds, resetWarnOnce, resolveEntry, resolveIgnitionRules, sampleClip, scaleClip, sealBlock, sealOpener, shotExtras, shotToHit, sideOnImpulse, sparkTargetFactor, stepKnock, surfaceOfMaterial, swingSoundId, takeLaunch, toolAnimationStep, twistStroke, unmarkedDrawings, useToHit };
|
package/dist/index.global.js
CHANGED
|
@@ -24,6 +24,7 @@ var GameContracts = (() => {
|
|
|
24
24
|
BLOW_IDS: () => BLOW_IDS,
|
|
25
25
|
BODY_FOLEY_IDS: () => BODY_FOLEY_IDS,
|
|
26
26
|
BODY_SOUND_IDS: () => BODY_SOUND_IDS,
|
|
27
|
+
DEFAULT_BLAST_IMPULSE: () => DEFAULT_BLAST_IMPULSE,
|
|
27
28
|
DEFAULT_BLAST_SHOVE: () => DEFAULT_BLAST_SHOVE,
|
|
28
29
|
DEFAULT_ENVIRONMENT: () => DEFAULT_ENVIRONMENT,
|
|
29
30
|
DEFAULT_IGNITION_RULES: () => DEFAULT_IGNITION_RULES,
|
|
@@ -31,6 +32,7 @@ var GameContracts = (() => {
|
|
|
31
32
|
DEFERRED_PRIORITY: () => DEFERRED_PRIORITY,
|
|
32
33
|
DEFERRED_QUEUE_ID: () => DEFERRED_QUEUE_ID,
|
|
33
34
|
FOOTSTEP_SOUND_IDS: () => FOOTSTEP_SOUND_IDS,
|
|
35
|
+
FRAGMENT_COVER: () => FRAGMENT_COVER,
|
|
34
36
|
FRAME_PHASES: () => FRAME_PHASES,
|
|
35
37
|
GAIT_IDS: () => GAIT_IDS,
|
|
36
38
|
HEAVY_LANDING_SPEED: () => HEAVY_LANDING_SPEED,
|
|
@@ -49,7 +51,9 @@ var GameContracts = (() => {
|
|
|
49
51
|
TOOL_CLIP: () => TOOL_CLIP,
|
|
50
52
|
TWIST_LIFT: () => TWIST_LIFT,
|
|
51
53
|
applyPatches: () => applyPatches,
|
|
54
|
+
blastBodySpeed: () => blastBodySpeed,
|
|
52
55
|
blastShove: () => blastShove,
|
|
56
|
+
bodyImpulse: () => bodyImpulse,
|
|
53
57
|
bodyMass: () => bodyMass,
|
|
54
58
|
checkAnimation: () => checkAnimation,
|
|
55
59
|
checkBench: () => checkBench,
|
|
@@ -72,6 +76,7 @@ var GameContracts = (() => {
|
|
|
72
76
|
kitOriginOf: () => kitOriginOf,
|
|
73
77
|
knockOf: () => knockOf,
|
|
74
78
|
landSoundId: () => landSoundId,
|
|
79
|
+
launchBody: () => launchBody,
|
|
75
80
|
leadClipEvents: () => leadClipEvents,
|
|
76
81
|
markKitOrigin: () => markKitOrigin,
|
|
77
82
|
mergeById: () => mergeById,
|
|
@@ -85,10 +90,12 @@ var GameContracts = (() => {
|
|
|
85
90
|
sealOpener: () => sealOpener,
|
|
86
91
|
shotExtras: () => shotExtras,
|
|
87
92
|
shotToHit: () => shotToHit,
|
|
93
|
+
sideOnImpulse: () => sideOnImpulse,
|
|
88
94
|
sparkTargetFactor: () => sparkTargetFactor,
|
|
89
95
|
stepKnock: () => stepKnock,
|
|
90
96
|
surfaceOfMaterial: () => surfaceOfMaterial,
|
|
91
97
|
swingSoundId: () => swingSoundId,
|
|
98
|
+
takeLaunch: () => takeLaunch,
|
|
92
99
|
toolAnimationStep: () => toolAnimationStep,
|
|
93
100
|
twistStroke: () => twistStroke,
|
|
94
101
|
unmarkedDrawings: () => unmarkedDrawings,
|
|
@@ -98,6 +105,7 @@ var GameContracts = (() => {
|
|
|
98
105
|
|
|
99
106
|
// src/blast-shove.ts
|
|
100
107
|
var DEFAULT_BLAST_SHOVE = { coupling: 0.02, maxSpeed: 20, lift: 0.3, minSpeed: 0.3, falloffPower: 2 };
|
|
108
|
+
var clampShare = (share) => Math.min(1, Math.max(0, share));
|
|
101
109
|
function blastShove(blast, target, options = {}) {
|
|
102
110
|
const o = { ...DEFAULT_BLAST_SHOVE, ...options };
|
|
103
111
|
const dx = target.position[0] - blast.point[0];
|
|
@@ -107,17 +115,41 @@ var GameContracts = (() => {
|
|
|
107
115
|
if (!(blast.radius > 0) || distance > blast.radius) return void 0;
|
|
108
116
|
const falloff = (1 - distance / blast.radius) ** o.falloffPower;
|
|
109
117
|
const mass = Math.max(target.mass, 0.05);
|
|
110
|
-
const
|
|
118
|
+
const reach = clampShare(blast.reach ?? 1);
|
|
119
|
+
const speed = Math.sqrt(reach) * Math.min(o.maxSpeed, Math.sqrt(2 * blast.energy * o.coupling / mass)) * falloff;
|
|
111
120
|
if (!(speed >= o.minSpeed)) return void 0;
|
|
112
121
|
const direction = distance > 1e-4 ? [dx / distance, dy / distance + o.lift, dz / distance] : [0, 1, 0];
|
|
113
122
|
const length = Math.hypot(direction[0], direction[1], direction[2]);
|
|
114
123
|
return { speed, direction: [direction[0] / length, direction[1] / length, direction[2] / length], distance, falloff };
|
|
115
124
|
}
|
|
116
125
|
|
|
126
|
+
// src/blast-impulse.ts
|
|
127
|
+
var DEFAULT_BLAST_IMPULSE = { bodyArea: 0.7, lift: 0.15, minSpeed: 0.3, tntPerJoule: 0.24 / 2e5 };
|
|
128
|
+
var NEAREST = 0.3;
|
|
129
|
+
function sideOnImpulse(tnt, distance) {
|
|
130
|
+
if (!(tnt > 0)) return 0;
|
|
131
|
+
const w3 = Math.cbrt(tnt);
|
|
132
|
+
const z = Math.max(distance, NEAREST) / w3;
|
|
133
|
+
const scaled = 0.067 * Math.sqrt(1 + (z / 0.23) ** 4) / (z * z * Math.cbrt(1 + (z / 1.55) ** 3));
|
|
134
|
+
return scaled * w3 * 100;
|
|
135
|
+
}
|
|
136
|
+
function bodyImpulse(tnt, distance) {
|
|
137
|
+
if (!(tnt > 0)) return 0;
|
|
138
|
+
const z = Math.max(distance, NEAREST) / Math.cbrt(tnt);
|
|
139
|
+
return sideOnImpulse(tnt, distance) * (2 + 4 / (1 + z * z));
|
|
140
|
+
}
|
|
141
|
+
function blastBodySpeed(tnt, distance, mass, reach = 1, options = {}) {
|
|
142
|
+
const area = options.bodyArea ?? DEFAULT_BLAST_IMPULSE.bodyArea;
|
|
143
|
+
return bodyImpulse(tnt, distance) * area * Math.max(0, reach) / Math.max(mass, 1);
|
|
144
|
+
}
|
|
145
|
+
|
|
117
146
|
// src/blast-knock.ts
|
|
118
147
|
var KNOCK_DOWN_SPEED = 2.5;
|
|
119
148
|
var KNOCKED_DOWN_ANGLE = 1.35;
|
|
120
149
|
var LIE_SECONDS = 1.6;
|
|
150
|
+
var WOUNDED_LIE_SECONDS = 6;
|
|
151
|
+
var FRAGMENT_COVER = 0.5;
|
|
152
|
+
var STUN_SECONDS = 4;
|
|
121
153
|
var STAND_UP_PER_SPEED = 0.25;
|
|
122
154
|
var FALL_SECONDS = 0.25;
|
|
123
155
|
var RISE_SECONDS = 0.6;
|
|
@@ -126,11 +158,38 @@ var GameContracts = (() => {
|
|
|
126
158
|
var KNOCK_CHEST = 1.1;
|
|
127
159
|
var CHEST = KNOCK_CHEST;
|
|
128
160
|
var bodyMass = (height, build = 1) => 70 * (height / 1.75) ** 2 * build;
|
|
129
|
-
function knockOf(blast, feet, mass, options) {
|
|
130
|
-
const
|
|
131
|
-
|
|
132
|
-
const
|
|
133
|
-
|
|
161
|
+
function knockOf(blast, feet, mass, options, impulse = {}) {
|
|
162
|
+
const o = { ...DEFAULT_BLAST_IMPULSE, ...impulse };
|
|
163
|
+
const chest = [feet[0], feet[1] + CHEST, feet[2]];
|
|
164
|
+
const dx = chest[0] - blast.point[0];
|
|
165
|
+
const dy = chest[1] - blast.point[1];
|
|
166
|
+
const dz = chest[2] - blast.point[2];
|
|
167
|
+
const distance = Math.hypot(dx, dy, dz);
|
|
168
|
+
if (!(blast.radius > 0) || distance > blast.radius) return void 0;
|
|
169
|
+
const reach = Math.max(0, Math.min(1, blast.reach ?? 1));
|
|
170
|
+
const tnt = blast.tnt ?? blast.energy * o.tntPerJoule;
|
|
171
|
+
let speed = blastBodySpeed(tnt, distance, mass, reach, o);
|
|
172
|
+
const minSpeed = impulse.minSpeed ?? options?.minSpeed ?? o.minSpeed;
|
|
173
|
+
if (speed < minSpeed) speed = 0;
|
|
174
|
+
const struck = reach >= FRAGMENT_COVER;
|
|
175
|
+
const wounded = struck && blast.lethalRadius !== void 0 && distance <= blast.lethalRadius;
|
|
176
|
+
const edge = 1 - distance / blast.radius;
|
|
177
|
+
const stunSeconds = struck ? STUN_SECONDS * edge * edge * reach : 0;
|
|
178
|
+
if (speed === 0 && !wounded && stunSeconds < 0.25) return void 0;
|
|
179
|
+
const horizontal = Math.hypot(dx, dz);
|
|
180
|
+
const away = horizontal > 1e-4 ? [dx / horizontal, o.lift, dz / horizontal] : [0, 1, 0];
|
|
181
|
+
const length = Math.hypot(away[0], away[1], away[2]);
|
|
182
|
+
const velocity = [away[0] / length * speed, away[1] / length * speed, away[2] / length * speed];
|
|
183
|
+
return {
|
|
184
|
+
velocity,
|
|
185
|
+
airborne: velocity[1] > 0.5,
|
|
186
|
+
lying: 0,
|
|
187
|
+
lieLeft: wounded ? WOUNDED_LIE_SECONDS : 0,
|
|
188
|
+
away: horizontal > 1e-4 ? [dx / horizontal, 0, dz / horizontal] : [0, 0, 0],
|
|
189
|
+
down: speed >= KNOCK_DOWN_SPEED || wounded,
|
|
190
|
+
...wounded ? { wounded } : {},
|
|
191
|
+
...stunSeconds >= 0.25 ? { stunSeconds } : {}
|
|
192
|
+
};
|
|
134
193
|
}
|
|
135
194
|
function stepKnock(knock, position, dt, groundAt, alive) {
|
|
136
195
|
const v = knock.velocity;
|
|
@@ -154,18 +213,25 @@ var GameContracts = (() => {
|
|
|
154
213
|
}
|
|
155
214
|
const moving = horizontal > 0.05 || knock.airborne;
|
|
156
215
|
if (knock.down) {
|
|
157
|
-
if (moving) knock.lying = Math.min(1, knock.lying + dt / FALL_SECONDS);
|
|
158
|
-
else {
|
|
159
|
-
knock.
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
knock.lieLeft -= dt;
|
|
163
|
-
if (knock.lieLeft <= 0) knock.down = false;
|
|
164
|
-
}
|
|
216
|
+
if (moving || knock.lying < 1) knock.lying = Math.min(1, knock.lying + dt / FALL_SECONDS);
|
|
217
|
+
else if (alive) {
|
|
218
|
+
knock.lieLeft = knock.lieLeft > 0 ? knock.lieLeft : LIE_SECONDS + Math.hypot(v[0], v[2]) * STAND_UP_PER_SPEED;
|
|
219
|
+
knock.lieLeft -= dt;
|
|
220
|
+
if (knock.lieLeft <= 0) knock.down = false;
|
|
165
221
|
}
|
|
166
222
|
} else if (knock.lying > 0) knock.lying = Math.max(0, knock.lying - dt / RISE_SECONDS);
|
|
167
223
|
return !moving && !knock.down && knock.lying === 0;
|
|
168
224
|
}
|
|
225
|
+
var LAUNCHED = "launched";
|
|
226
|
+
function launchBody(root, velocity) {
|
|
227
|
+
root.userData[LAUNCHED] = [velocity[0], velocity[1], velocity[2]];
|
|
228
|
+
}
|
|
229
|
+
function takeLaunch(root) {
|
|
230
|
+
const velocity = root.userData[LAUNCHED];
|
|
231
|
+
if (!velocity) return void 0;
|
|
232
|
+
delete root.userData[LAUNCHED];
|
|
233
|
+
return { velocity: [velocity[0], velocity[1], velocity[2]], airborne: true, lying: 0, lieLeft: 0, down: true };
|
|
234
|
+
}
|
|
169
235
|
|
|
170
236
|
// src/impact-cost.ts
|
|
171
237
|
var DEFAULT_COST_READS = 1e4;
|
|
@@ -1190,6 +1256,8 @@ var GameContracts = (() => {
|
|
|
1190
1256
|
mortar: "concrete",
|
|
1191
1257
|
stone: "concrete",
|
|
1192
1258
|
brick: "concrete",
|
|
1259
|
+
cobble: "concrete",
|
|
1260
|
+
paver: "concrete",
|
|
1193
1261
|
plaster: "concrete",
|
|
1194
1262
|
asphalt: "asphalt",
|
|
1195
1263
|
wood_soft: "wood",
|
|
@@ -1200,6 +1268,8 @@ var GameContracts = (() => {
|
|
|
1200
1268
|
ceramic: "tile",
|
|
1201
1269
|
plastic: "tile",
|
|
1202
1270
|
soil: "dirt",
|
|
1271
|
+
mud: "dirt",
|
|
1272
|
+
clay: "dirt",
|
|
1203
1273
|
wax: "dirt",
|
|
1204
1274
|
flesh_fruit: "dirt",
|
|
1205
1275
|
turf: "grass",
|
|
@@ -1207,6 +1277,8 @@ var GameContracts = (() => {
|
|
|
1207
1277
|
cactus: "grass",
|
|
1208
1278
|
gravel: "gravel",
|
|
1209
1279
|
sand: "sand",
|
|
1280
|
+
// no snow surface yet: packed snow crunches closest to sand underfoot
|
|
1281
|
+
snow: "sand",
|
|
1210
1282
|
steel: "metal",
|
|
1211
1283
|
cast_iron: "metal",
|
|
1212
1284
|
aluminium: "metal",
|