@adatechnology/game-contracts 0.23.0 → 0.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +67 -4
- package/dist/index.global.js +65 -13
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +65 -13
- 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`). */
|
|
@@ -969,6 +972,13 @@ interface BlastSource {
|
|
|
969
972
|
readonly energy: number;
|
|
970
973
|
readonly radius: number;
|
|
971
974
|
readonly reach?: number;
|
|
975
|
+
/**
|
|
976
|
+
* 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
|
|
977
|
+
* takes the charge from `energy` by `BlastImpulseOptions.tntPerJoule`.
|
|
978
|
+
*/
|
|
979
|
+
readonly tnt?: number;
|
|
980
|
+
/** 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. */
|
|
981
|
+
readonly lethalRadius?: number;
|
|
972
982
|
}
|
|
973
983
|
/** 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
984
|
interface BlastShove {
|
|
@@ -988,10 +998,45 @@ declare function blastShove(blast: BlastSource, target: {
|
|
|
988
998
|
readonly mass: number;
|
|
989
999
|
}, options?: BlastShoveOptions): BlastShove | undefined;
|
|
990
1000
|
|
|
1001
|
+
/**
|
|
1002
|
+
* 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
|
|
1003
|
+
* `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,
|
|
1004
|
+
* 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.
|
|
1005
|
+
*/
|
|
1006
|
+
/** The numbers of the body a blast wave pushes. All have a default for a standing adult. */
|
|
1007
|
+
interface BlastImpulseOptions {
|
|
1008
|
+
/** Square metres of the body the wave meets: about 1.75 m tall by 0.4 m wide (default 0.7). */
|
|
1009
|
+
readonly bodyArea?: number;
|
|
1010
|
+
/** How much of the push goes up: the direction is `(away, lift)` normalised (default 0.15: the wave runs along the ground). */
|
|
1011
|
+
readonly lift?: number;
|
|
1012
|
+
/** Below this speed (m/s) the body does not move (default 0.3). */
|
|
1013
|
+
readonly minSpeed?: number;
|
|
1014
|
+
/**
|
|
1015
|
+
* 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
|
|
1016
|
+
* 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.
|
|
1017
|
+
*/
|
|
1018
|
+
readonly tntPerJoule?: number;
|
|
1019
|
+
}
|
|
1020
|
+
declare const DEFAULT_BLAST_IMPULSE: Readonly<Required<BlastImpulseOptions>>;
|
|
1021
|
+
/**
|
|
1022
|
+
* 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),
|
|
1023
|
+
* `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)`.
|
|
1024
|
+
*/
|
|
1025
|
+
declare function sideOnImpulse(tnt: number, distance: number): number;
|
|
1026
|
+
/**
|
|
1027
|
+
* 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,
|
|
1028
|
+
* 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)`).
|
|
1029
|
+
*/
|
|
1030
|
+
declare function bodyImpulse(tnt: number, distance: number): number;
|
|
1031
|
+
/** 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. */
|
|
1032
|
+
declare function blastBodySpeed(tnt: number, distance: number, mass: number, reach?: number, options?: BlastImpulseOptions): number;
|
|
1033
|
+
|
|
991
1034
|
/** From this speed (m/s) a blast takes a standing body off its feet. Below it the body is only pushed. */
|
|
992
1035
|
declare const KNOCK_DOWN_SPEED = 2.5;
|
|
993
1036
|
/** The angle of a body lying where it fell (the same tilt a dead body takes). */
|
|
994
1037
|
declare const KNOCKED_DOWN_ANGLE = 1.35;
|
|
1038
|
+
/** 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. */
|
|
1039
|
+
declare const FRAGMENT_COVER = 0.5;
|
|
995
1040
|
/** Height of the chest above the feet: where the blast takes the body. */
|
|
996
1041
|
declare const KNOCK_CHEST = 1.1;
|
|
997
1042
|
/** 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 +1049,23 @@ interface Knock {
|
|
|
1004
1049
|
lieLeft: number;
|
|
1005
1050
|
/** Knocked off its feet by this blast. */
|
|
1006
1051
|
down: boolean;
|
|
1052
|
+
/** Floored by its wounds: inside the lethal radius and not behind cover. It lies longer and falls where it stood. */
|
|
1053
|
+
wounded?: boolean;
|
|
1054
|
+
/** Seconds of stun the blast gave the body: dizziness and ringing ears. */
|
|
1055
|
+
stunSeconds?: number;
|
|
1056
|
+
/** The horizontal unit direction away from the blast, even when the push is too weak to move the body: the way it falls. */
|
|
1057
|
+
away?: Vec3;
|
|
1007
1058
|
}
|
|
1008
1059
|
/** The mass of a body in kg from its height (m) and its build (1 = average): 70 kg at 1.75 m. */
|
|
1009
1060
|
declare const bodyMass: (height: number, build?: number) => number;
|
|
1010
1061
|
/**
|
|
1011
|
-
* What a blast does to a body standing at `feet
|
|
1012
|
-
*
|
|
1062
|
+
* 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.
|
|
1063
|
+
*
|
|
1064
|
+
* 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
|
|
1065
|
+
* 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
|
|
1066
|
+
* 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
1067
|
*/
|
|
1014
|
-
declare function knockOf(blast: BlastSource, feet: Vec3, mass: number, options?: BlastShoveOptions): Knock | undefined;
|
|
1068
|
+
declare function knockOf(blast: BlastSource, feet: Vec3, mass: number, options?: BlastShoveOptions, impulse?: BlastImpulseOptions): Knock | undefined;
|
|
1015
1069
|
/**
|
|
1016
1070
|
* 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
1071
|
* body is on its feet and still, and the knock can be dropped.
|
|
@@ -2290,6 +2344,10 @@ type HostEvent =
|
|
|
2290
2344
|
radius: number;
|
|
2291
2345
|
cause: string;
|
|
2292
2346
|
explosive?: string;
|
|
2347
|
+
/** Kilograms of TNT equivalent of the charge, when the explosive says it: the blast wave that pushes bodies is read from it (`knockOf`). */
|
|
2348
|
+
tnt?: number;
|
|
2349
|
+
/** Inside this radius (metres) the blast is lethal to a body it reaches. */
|
|
2350
|
+
lethalRadius?: number;
|
|
2293
2351
|
}
|
|
2294
2352
|
/** The player crouched or stood up, or the camera mode changed; read the new state with `host.player()`. */
|
|
2295
2353
|
| {
|
|
@@ -2522,6 +2580,11 @@ interface ModuleHost {
|
|
|
2522
2580
|
* that keeps its camera to itself leaves it out.
|
|
2523
2581
|
*/
|
|
2524
2582
|
setViewCamera?(camera: unknown | null): void;
|
|
2583
|
+
/**
|
|
2584
|
+
* 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,
|
|
2585
|
+
* the panels and the room's other keys keep working. A host without a walking player leaves it out.
|
|
2586
|
+
*/
|
|
2587
|
+
holdPlayer?(held: boolean): void;
|
|
2525
2588
|
/** Lent only to a module that declares controls, layers or metrics. */
|
|
2526
2589
|
bench?: ModuleBench;
|
|
2527
2590
|
/** 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 +2870,4 @@ declare function footprintBlocker(object: FootprintObject | (() => FootprintObje
|
|
|
2807
2870
|
/** @deprecated Import it from `@adatechnology/game-contracts/testing`. */
|
|
2808
2871
|
declare const resetWarnOnce: () => void;
|
|
2809
2872
|
|
|
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 };
|
|
2873
|
+
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 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, leadClipEvents, markKitOrigin, mergeById, removeIds, resetWarnOnce, resolveEntry, resolveIgnitionRules, sampleClip, scaleClip, sealBlock, sealOpener, shotExtras, shotToHit, sideOnImpulse, sparkTargetFactor, stepKnock, surfaceOfMaterial, swingSoundId, 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,
|
|
@@ -85,6 +89,7 @@ var GameContracts = (() => {
|
|
|
85
89
|
sealOpener: () => sealOpener,
|
|
86
90
|
shotExtras: () => shotExtras,
|
|
87
91
|
shotToHit: () => shotToHit,
|
|
92
|
+
sideOnImpulse: () => sideOnImpulse,
|
|
88
93
|
sparkTargetFactor: () => sparkTargetFactor,
|
|
89
94
|
stepKnock: () => stepKnock,
|
|
90
95
|
surfaceOfMaterial: () => surfaceOfMaterial,
|
|
@@ -114,10 +119,33 @@ var GameContracts = (() => {
|
|
|
114
119
|
return { speed, direction: [direction[0] / length, direction[1] / length, direction[2] / length], distance, falloff };
|
|
115
120
|
}
|
|
116
121
|
|
|
122
|
+
// src/blast-impulse.ts
|
|
123
|
+
var DEFAULT_BLAST_IMPULSE = { bodyArea: 0.7, lift: 0.15, minSpeed: 0.3, tntPerJoule: 0.24 / 2e5 };
|
|
124
|
+
var NEAREST = 0.3;
|
|
125
|
+
function sideOnImpulse(tnt, distance) {
|
|
126
|
+
if (!(tnt > 0)) return 0;
|
|
127
|
+
const w3 = Math.cbrt(tnt);
|
|
128
|
+
const z = Math.max(distance, NEAREST) / w3;
|
|
129
|
+
const scaled = 0.067 * Math.sqrt(1 + (z / 0.23) ** 4) / (z * z * Math.cbrt(1 + (z / 1.55) ** 3));
|
|
130
|
+
return scaled * w3 * 100;
|
|
131
|
+
}
|
|
132
|
+
function bodyImpulse(tnt, distance) {
|
|
133
|
+
if (!(tnt > 0)) return 0;
|
|
134
|
+
const z = Math.max(distance, NEAREST) / Math.cbrt(tnt);
|
|
135
|
+
return sideOnImpulse(tnt, distance) * (2 + 4 / (1 + z * z));
|
|
136
|
+
}
|
|
137
|
+
function blastBodySpeed(tnt, distance, mass, reach = 1, options = {}) {
|
|
138
|
+
const area = options.bodyArea ?? DEFAULT_BLAST_IMPULSE.bodyArea;
|
|
139
|
+
return bodyImpulse(tnt, distance) * area * Math.max(0, reach) / Math.max(mass, 1);
|
|
140
|
+
}
|
|
141
|
+
|
|
117
142
|
// src/blast-knock.ts
|
|
118
143
|
var KNOCK_DOWN_SPEED = 2.5;
|
|
119
144
|
var KNOCKED_DOWN_ANGLE = 1.35;
|
|
120
145
|
var LIE_SECONDS = 1.6;
|
|
146
|
+
var WOUNDED_LIE_SECONDS = 6;
|
|
147
|
+
var FRAGMENT_COVER = 0.5;
|
|
148
|
+
var STUN_SECONDS = 4;
|
|
121
149
|
var STAND_UP_PER_SPEED = 0.25;
|
|
122
150
|
var FALL_SECONDS = 0.25;
|
|
123
151
|
var RISE_SECONDS = 0.6;
|
|
@@ -126,11 +154,38 @@ var GameContracts = (() => {
|
|
|
126
154
|
var KNOCK_CHEST = 1.1;
|
|
127
155
|
var CHEST = KNOCK_CHEST;
|
|
128
156
|
var bodyMass = (height, build = 1) => 70 * (height / 1.75) ** 2 * build;
|
|
129
|
-
function knockOf(blast, feet, mass, options) {
|
|
130
|
-
const
|
|
131
|
-
|
|
132
|
-
const
|
|
133
|
-
|
|
157
|
+
function knockOf(blast, feet, mass, options, impulse = {}) {
|
|
158
|
+
const o = { ...DEFAULT_BLAST_IMPULSE, ...impulse };
|
|
159
|
+
const chest = [feet[0], feet[1] + CHEST, feet[2]];
|
|
160
|
+
const dx = chest[0] - blast.point[0];
|
|
161
|
+
const dy = chest[1] - blast.point[1];
|
|
162
|
+
const dz = chest[2] - blast.point[2];
|
|
163
|
+
const distance = Math.hypot(dx, dy, dz);
|
|
164
|
+
if (!(blast.radius > 0) || distance > blast.radius) return void 0;
|
|
165
|
+
const reach = Math.max(0, Math.min(1, blast.reach ?? 1));
|
|
166
|
+
const tnt = blast.tnt ?? blast.energy * o.tntPerJoule;
|
|
167
|
+
let speed = blastBodySpeed(tnt, distance, mass, reach, o);
|
|
168
|
+
const minSpeed = impulse.minSpeed ?? options?.minSpeed ?? o.minSpeed;
|
|
169
|
+
if (speed < minSpeed) speed = 0;
|
|
170
|
+
const struck = reach >= FRAGMENT_COVER;
|
|
171
|
+
const wounded = struck && blast.lethalRadius !== void 0 && distance <= blast.lethalRadius;
|
|
172
|
+
const edge = 1 - distance / blast.radius;
|
|
173
|
+
const stunSeconds = struck ? STUN_SECONDS * edge * edge * reach : 0;
|
|
174
|
+
if (speed === 0 && !wounded && stunSeconds < 0.25) return void 0;
|
|
175
|
+
const horizontal = Math.hypot(dx, dz);
|
|
176
|
+
const away = horizontal > 1e-4 ? [dx / horizontal, o.lift, dz / horizontal] : [0, 1, 0];
|
|
177
|
+
const length = Math.hypot(away[0], away[1], away[2]);
|
|
178
|
+
const velocity = [away[0] / length * speed, away[1] / length * speed, away[2] / length * speed];
|
|
179
|
+
return {
|
|
180
|
+
velocity,
|
|
181
|
+
airborne: velocity[1] > 0.5,
|
|
182
|
+
lying: 0,
|
|
183
|
+
lieLeft: wounded ? WOUNDED_LIE_SECONDS : 0,
|
|
184
|
+
away: horizontal > 1e-4 ? [dx / horizontal, 0, dz / horizontal] : [0, 0, 0],
|
|
185
|
+
down: speed >= KNOCK_DOWN_SPEED || wounded,
|
|
186
|
+
...wounded ? { wounded } : {},
|
|
187
|
+
...stunSeconds >= 0.25 ? { stunSeconds } : {}
|
|
188
|
+
};
|
|
134
189
|
}
|
|
135
190
|
function stepKnock(knock, position, dt, groundAt, alive) {
|
|
136
191
|
const v = knock.velocity;
|
|
@@ -154,14 +209,11 @@ var GameContracts = (() => {
|
|
|
154
209
|
}
|
|
155
210
|
const moving = horizontal > 0.05 || knock.airborne;
|
|
156
211
|
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
|
-
}
|
|
212
|
+
if (moving || knock.lying < 1) knock.lying = Math.min(1, knock.lying + dt / FALL_SECONDS);
|
|
213
|
+
else if (alive) {
|
|
214
|
+
knock.lieLeft = knock.lieLeft > 0 ? knock.lieLeft : LIE_SECONDS + Math.hypot(v[0], v[2]) * STAND_UP_PER_SPEED;
|
|
215
|
+
knock.lieLeft -= dt;
|
|
216
|
+
if (knock.lieLeft <= 0) knock.down = false;
|
|
165
217
|
}
|
|
166
218
|
} else if (knock.lying > 0) knock.lying = Math.max(0, knock.lying - dt / RISE_SECONDS);
|
|
167
219
|
return !moving && !knock.down && knock.lying === 0;
|