@adatechnology/game-weather-three 0.0.0-stage → 0.2.1
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/LICENSE +21 -0
- package/README.md +48 -2
- package/dist/index.d.ts +331 -0
- package/dist/index.global.js +2403 -0
- package/dist/index.global.js.map +1 -0
- package/dist/index.js +537 -0
- package/dist/index.js.map +1 -0
- package/package.json +61 -3
|
@@ -0,0 +1,2403 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var GameWeatherThree = (() => {
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toCommonJS = (mod2) => __copyProps(__defProp({}, "__esModule", { value: true }), mod2);
|
|
20
|
+
|
|
21
|
+
// src/index.ts
|
|
22
|
+
var index_exports = {};
|
|
23
|
+
__export(index_exports, {
|
|
24
|
+
ASH: () => ASH,
|
|
25
|
+
FOG_EXP_FROM: () => FOG_EXP_FROM,
|
|
26
|
+
FOG_NEAR: () => FOG_NEAR,
|
|
27
|
+
FOG_ZONE_NEAR: () => FOG_ZONE_NEAR,
|
|
28
|
+
HEADLIGHTS: () => HEADLIGHTS,
|
|
29
|
+
HEAT_HAZE: () => HEAT_HAZE,
|
|
30
|
+
HEAT_HAZE_FRAGMENT: () => HEAT_HAZE_FRAGMENT,
|
|
31
|
+
HEAT_HAZE_VERTEX: () => HEAT_HAZE_VERTEX,
|
|
32
|
+
LIGHTNING: () => LIGHTNING,
|
|
33
|
+
MIST: () => MIST,
|
|
34
|
+
RAIN_CURTAIN: () => RAIN_CURTAIN,
|
|
35
|
+
RAIN_CURTAIN_FRAGMENT: () => RAIN_CURTAIN_FRAGMENT,
|
|
36
|
+
RAIN_CURTAIN_FULL_AT: () => RAIN_CURTAIN_FULL_AT,
|
|
37
|
+
RAIN_CURTAIN_PROFILES: () => RAIN_CURTAIN_PROFILES,
|
|
38
|
+
RAIN_CURTAIN_VERTEX: () => RAIN_CURTAIN_VERTEX,
|
|
39
|
+
SKY_DAY: () => SKY_DAY,
|
|
40
|
+
SKY_NIGHT: () => SKY_NIGHT,
|
|
41
|
+
SPLASH_FROM_MM: () => SPLASH_FROM_MM,
|
|
42
|
+
WEATHER_LAYERS: () => WEATHER_LAYERS,
|
|
43
|
+
ZONE_FOG_DEFAULTS: () => ZONE_FOG_DEFAULTS,
|
|
44
|
+
ZONE_LIGHT: () => ZONE_LIGHT,
|
|
45
|
+
createFog: () => createFog,
|
|
46
|
+
createHeadlights: () => createHeadlights,
|
|
47
|
+
createHeatHaze: () => createHeatHaze,
|
|
48
|
+
createLightning: () => createLightning,
|
|
49
|
+
createNearRain: () => createNearRain,
|
|
50
|
+
createRainCurtain: () => createRainCurtain,
|
|
51
|
+
createSky: () => createSky,
|
|
52
|
+
createWeatherRenderer: () => createWeatherRenderer,
|
|
53
|
+
createWeatherVisual: () => createWeatherVisual,
|
|
54
|
+
defaultHeadlightRule: () => defaultHeadlightRule,
|
|
55
|
+
densityForFar: () => densityForFar,
|
|
56
|
+
emitAirborne: () => emitAirborne,
|
|
57
|
+
fogOf: () => fogOf,
|
|
58
|
+
rainCurtainPositions: () => rainCurtainPositions,
|
|
59
|
+
weatherVisualTextOf: () => weatherVisualTextOf
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
// src/sky.ts
|
|
63
|
+
var SKY_NIGHT = 724760;
|
|
64
|
+
var SKY_DAY = 8885926;
|
|
65
|
+
var ZONE_LIGHT = { base: 0.35, sun: 0.65 };
|
|
66
|
+
var ZONE_FOG_DEFAULTS = { color: 3820090, far: 60 };
|
|
67
|
+
function createSky(THREE, scene) {
|
|
68
|
+
const night = new THREE.Color(SKY_NIGHT);
|
|
69
|
+
const day = new THREE.Color(SKY_DAY);
|
|
70
|
+
const zoneColor = new THREE.Color(ZONE_FOG_DEFAULTS.color);
|
|
71
|
+
const tint = new THREE.Color();
|
|
72
|
+
const color = new THREE.Color();
|
|
73
|
+
return {
|
|
74
|
+
color,
|
|
75
|
+
update(sample, zone) {
|
|
76
|
+
color.lerpColors(night, day, sample.sun);
|
|
77
|
+
color.multiplyScalar(sample.skyScale);
|
|
78
|
+
if (zone && zone.weight > 0) {
|
|
79
|
+
zoneColor.setHex(zone.color ?? ZONE_FOG_DEFAULTS.color);
|
|
80
|
+
color.lerp(tint.copy(zoneColor).multiplyScalar(ZONE_LIGHT.base + sample.sun * ZONE_LIGHT.sun), zone.weight);
|
|
81
|
+
}
|
|
82
|
+
const background = scene.background;
|
|
83
|
+
if (background && background.isColor) background.copy(color);
|
|
84
|
+
else scene.background = color.clone();
|
|
85
|
+
return color;
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// src/fog.ts
|
|
91
|
+
var FOG_NEAR = 25;
|
|
92
|
+
var FOG_ZONE_NEAR = 4;
|
|
93
|
+
var FOG_EXP_FROM = 5e-4;
|
|
94
|
+
var densityForFar = (far) => Math.sqrt(Math.log(50)) / far;
|
|
95
|
+
function fogOf(sample, zone, expFrom = FOG_EXP_FROM) {
|
|
96
|
+
const weight = zone?.weight ?? 0;
|
|
97
|
+
const zoneFar = zone?.far ?? ZONE_FOG_DEFAULTS.far;
|
|
98
|
+
if (sample.fogDensity >= expFrom) return { mode: "exp2", density: sample.fogDensity + (densityForFar(zoneFar) - sample.fogDensity) * weight };
|
|
99
|
+
return { mode: "linear", near: FOG_NEAR + (FOG_ZONE_NEAR - FOG_NEAR) * weight, far: sample.fogFar + (zoneFar - sample.fogFar) * weight };
|
|
100
|
+
}
|
|
101
|
+
function createFog(THREE, scene, options = {}) {
|
|
102
|
+
const original = scene.fog;
|
|
103
|
+
const kept = original && original.isFog ? original.clone() : original;
|
|
104
|
+
return {
|
|
105
|
+
update(sample, sky, zone) {
|
|
106
|
+
const values = fogOf(sample, zone, options.expFrom);
|
|
107
|
+
const current = scene.fog;
|
|
108
|
+
if (values.mode === "linear") {
|
|
109
|
+
if (current?.isFog) {
|
|
110
|
+
current.color.copy(sky);
|
|
111
|
+
current.near = values.near;
|
|
112
|
+
current.far = values.far;
|
|
113
|
+
} else scene.fog = new THREE.Fog(sky.getHex(), values.near, values.far);
|
|
114
|
+
} else if (current?.isFogExp2) {
|
|
115
|
+
current.color.copy(sky);
|
|
116
|
+
current.density = values.density;
|
|
117
|
+
} else scene.fog = new THREE.FogExp2(sky.getHex(), values.density);
|
|
118
|
+
const fog = scene.fog;
|
|
119
|
+
fog.color.copy(sky);
|
|
120
|
+
},
|
|
121
|
+
clear() {
|
|
122
|
+
scene.fog = kept && kept.isFog ? kept.clone() : kept ?? null;
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
var MIST = { box: { x: [-14, 10], y: [0.2, 1.1], z: [-3, 8] }, drift: [0.15, 0.35], life: [9, 13], size: [3, 5], grow: 1.4, color: 8227488, alpha: 0.13, fadeIn: 0.35 };
|
|
127
|
+
var ASH = { box: { x: [-10, 8], y: [4, 6], z: [-3, 7] }, fall: -0.35, life: [8, 12], size: [0.025, 0.04], color: 10525328, alpha: 0.75, fadeIn: 0.1 };
|
|
128
|
+
function emitAirborne(engine, sample, dt, camera2) {
|
|
129
|
+
const { random } = engine;
|
|
130
|
+
const around = (box) => [
|
|
131
|
+
camera2[0] + random.between(box.x[0], box.x[1]),
|
|
132
|
+
random.between(box.y[0], box.y[1]),
|
|
133
|
+
camera2[2] + random.between(box.z[0], box.z[1])
|
|
134
|
+
];
|
|
135
|
+
if (sample.mistPerSecond > 0) {
|
|
136
|
+
engine.emit("weather-mist", "normal", sample.mistPerSecond, dt, () => ({
|
|
137
|
+
p: around(MIST.box),
|
|
138
|
+
v: [random.between(MIST.drift[0], MIST.drift[1]), 0, random.between(-0.05, 0.05)],
|
|
139
|
+
sp: 0,
|
|
140
|
+
life: MIST.life,
|
|
141
|
+
size: MIST.size,
|
|
142
|
+
grow: MIST.grow,
|
|
143
|
+
c0: MIST.color,
|
|
144
|
+
a: MIST.alpha,
|
|
145
|
+
fi: MIST.fadeIn
|
|
146
|
+
}));
|
|
147
|
+
}
|
|
148
|
+
if (sample.ashPerSecond > 0) {
|
|
149
|
+
engine.emit("weather-ash", "normal", sample.ashPerSecond, dt, () => ({
|
|
150
|
+
p: around(ASH.box),
|
|
151
|
+
v: [random.between(0.1, 0.4), ASH.fall, random.between(-0.1, 0.1)],
|
|
152
|
+
sp: [0.05, 0.15],
|
|
153
|
+
life: ASH.life,
|
|
154
|
+
size: ASH.size,
|
|
155
|
+
c0: ASH.color,
|
|
156
|
+
a: ASH.alpha,
|
|
157
|
+
fi: ASH.fadeIn,
|
|
158
|
+
gnd: 1
|
|
159
|
+
}));
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// src/headlights.ts
|
|
164
|
+
var HEADLIGHTS = {
|
|
165
|
+
spot: { color: 16773584, intensity: 2.4, distance: 26, angle: 0.33, penumbra: 0.5, decay: 1.6 },
|
|
166
|
+
/** Lamp position on the car (x is mirrored), where the spot points, and the cone drawn in the air. */
|
|
167
|
+
lamp: [0.65, 0.74, 2.15],
|
|
168
|
+
aim: [0.65, 0.2, 12],
|
|
169
|
+
cone: { radius: 2.4, length: 9, segments: 18, color: 16773584, opacity: 0.06 },
|
|
170
|
+
lens: { on: 16773584, off: 3815988 },
|
|
171
|
+
/** Lit drops a second, thrown into the beam 1 to 13 m ahead (W1176). */
|
|
172
|
+
lit: { rate: 600, depth: [1, 13], spread: 0.33, color: 13622512, alpha: 0.9, life: 0.06, len: 0.035, velocity: [0.8, -14, 0] },
|
|
173
|
+
/** Beyond this many metres a car keeps only the cone: no real light (W-b text of `farol`). */
|
|
174
|
+
lightRange: 40
|
|
175
|
+
};
|
|
176
|
+
var defaultHeadlightRule = (sample) => sample.nightFactor > 0.3 || sample.rain > 0 || sample.fogDensity > 0.02 || sample.visibility < 150;
|
|
177
|
+
function createHeadlights(THREE, rules = {}) {
|
|
178
|
+
const rigs = /* @__PURE__ */ new Set();
|
|
179
|
+
const cone = HEADLIGHTS.cone;
|
|
180
|
+
const lampWorld = new THREE.Vector3();
|
|
181
|
+
const aimWorld = new THREE.Vector3();
|
|
182
|
+
const forward = new THREE.Vector3();
|
|
183
|
+
const rule = rules.lit ?? defaultHeadlightRule;
|
|
184
|
+
const range = rules.lightRange ?? HEADLIGHTS.lightRange;
|
|
185
|
+
function attach(car, lens2) {
|
|
186
|
+
const spots = [];
|
|
187
|
+
const cones = [];
|
|
188
|
+
const targets = [];
|
|
189
|
+
for (const side of [-1, 1]) {
|
|
190
|
+
const spot = new THREE.SpotLight(HEADLIGHTS.spot.color, 0, HEADLIGHTS.spot.distance, HEADLIGHTS.spot.angle, HEADLIGHTS.spot.penumbra, HEADLIGHTS.spot.decay);
|
|
191
|
+
spot.position.set(side * HEADLIGHTS.lamp[0], HEADLIGHTS.lamp[1], HEADLIGHTS.lamp[2]);
|
|
192
|
+
const target = new THREE.Object3D();
|
|
193
|
+
target.position.set(side * HEADLIGHTS.aim[0], HEADLIGHTS.aim[1], HEADLIGHTS.aim[2]);
|
|
194
|
+
car.add(spot, target);
|
|
195
|
+
spot.target = target;
|
|
196
|
+
const geometry = new THREE.ConeGeometry(cone.radius, cone.length, cone.segments, 1, true);
|
|
197
|
+
geometry.translate(0, -cone.length / 2, 0);
|
|
198
|
+
geometry.rotateX(-Math.PI / 2);
|
|
199
|
+
const material = new THREE.MeshBasicMaterial({ color: cone.color, transparent: true, opacity: cone.opacity, blending: THREE.AdditiveBlending, depthWrite: false, side: THREE.DoubleSide, fog: false });
|
|
200
|
+
const beam = new THREE.Mesh(geometry, material);
|
|
201
|
+
beam.position.set(side * HEADLIGHTS.lamp[0], HEADLIGHTS.lamp[1], HEADLIGHTS.lamp[2]);
|
|
202
|
+
beam.visible = false;
|
|
203
|
+
car.add(beam);
|
|
204
|
+
spots.push(spot);
|
|
205
|
+
cones.push(beam);
|
|
206
|
+
targets.push(target);
|
|
207
|
+
}
|
|
208
|
+
const rig = { car, spots, cones, lens: lens2, targets };
|
|
209
|
+
rigs.add(rig);
|
|
210
|
+
return () => {
|
|
211
|
+
rigs.delete(rig);
|
|
212
|
+
for (const object of [...spots, ...cones, ...targets]) car.remove(object);
|
|
213
|
+
for (const beam of cones) {
|
|
214
|
+
beam.geometry.dispose();
|
|
215
|
+
beam.material.dispose();
|
|
216
|
+
}
|
|
217
|
+
for (const spot of spots) spot.dispose();
|
|
218
|
+
lens2?.color.setHex(HEADLIGHTS.lens.off);
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
return {
|
|
222
|
+
attach,
|
|
223
|
+
update(sample, dt, camera2, engine, enabled = true) {
|
|
224
|
+
const on = enabled && rule(sample);
|
|
225
|
+
let index = 0;
|
|
226
|
+
for (const rig of rigs) {
|
|
227
|
+
rig.car.updateWorldMatrix(true, false);
|
|
228
|
+
lampWorld.set(0, HEADLIGHTS.lamp[1], HEADLIGHTS.lamp[2]).applyMatrix4(rig.car.matrixWorld);
|
|
229
|
+
const near = Math.hypot(lampWorld.x - camera2[0], lampWorld.z - camera2[2]) <= range;
|
|
230
|
+
for (const spot of rig.spots) spot.intensity = on && near ? HEADLIGHTS.spot.intensity : 0;
|
|
231
|
+
for (const beam of rig.cones) beam.visible = on;
|
|
232
|
+
rig.lens?.color.setHex(on ? HEADLIGHTS.lens.on : HEADLIGHTS.lens.off);
|
|
233
|
+
if (!on || !engine || sample.rain <= 0 || !near) {
|
|
234
|
+
index++;
|
|
235
|
+
continue;
|
|
236
|
+
}
|
|
237
|
+
aimWorld.set(0, HEADLIGHTS.lamp[1], HEADLIGHTS.lamp[2] + 1).applyMatrix4(rig.car.matrixWorld);
|
|
238
|
+
forward.copy(aimWorld).sub(lampWorld).normalize();
|
|
239
|
+
const side = [forward.z, -forward.x];
|
|
240
|
+
const { random } = engine;
|
|
241
|
+
const lit = HEADLIGHTS.lit;
|
|
242
|
+
engine.emit(`weather-lit-${index}`, "streak", lit.rate, dt, () => {
|
|
243
|
+
const depth = random.between(lit.depth[0], lit.depth[1]);
|
|
244
|
+
const spread = depth * lit.spread * Math.sqrt(random.next());
|
|
245
|
+
const turn = random.between(0, 6.283);
|
|
246
|
+
return {
|
|
247
|
+
p: [lampWorld.x + forward.x * depth + side[0] * Math.cos(turn) * spread, lampWorld.y + forward.y * depth + Math.sin(turn) * spread * 0.6, lampWorld.z + forward.z * depth + side[1] * Math.cos(turn) * spread],
|
|
248
|
+
v: lit.velocity,
|
|
249
|
+
sp: 0,
|
|
250
|
+
life: lit.life,
|
|
251
|
+
len: lit.len,
|
|
252
|
+
c0: lit.color,
|
|
253
|
+
a: lit.alpha
|
|
254
|
+
};
|
|
255
|
+
});
|
|
256
|
+
index++;
|
|
257
|
+
}
|
|
258
|
+
},
|
|
259
|
+
count: () => rigs.size,
|
|
260
|
+
dispose() {
|
|
261
|
+
for (const rig of [...rigs]) {
|
|
262
|
+
rigs.delete(rig);
|
|
263
|
+
for (const object of [...rig.spots, ...rig.cones, ...rig.targets]) rig.car.remove(object);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// src/heat-haze.ts
|
|
270
|
+
var HEAT_HAZE = { opacity: 0.09, bands: 38, rise: 1.4, color: [1, 0.93, 0.82] };
|
|
271
|
+
var HEAT_HAZE_VERTEX = "varying vec2 vUv; void main(){ vUv = uv; gl_Position = vec4(position.xy, 0., 1.); }";
|
|
272
|
+
var HEAT_HAZE_FRAGMENT = "uniform float uTime; uniform float uHaze; uniform vec3 uColor; varying vec2 vUv; void main(){ float low = 1. - smoothstep(0.15, 0.7, vUv.y); float wave = sin(vUv.y*38. - uTime*1.4 + sin(vUv.x*11. + uTime*.7)*2.2) * .5 + .5; gl_FragColor = vec4(uColor, uHaze*low*wave*.09); }";
|
|
273
|
+
function createHeatHaze(THREE) {
|
|
274
|
+
const uniforms = { uTime: { value: 0 }, uHaze: { value: 0 }, uColor: { value: new THREE.Vector3(...HEAT_HAZE.color) } };
|
|
275
|
+
const material = new THREE.ShaderMaterial({ uniforms, vertexShader: HEAT_HAZE_VERTEX, fragmentShader: HEAT_HAZE_FRAGMENT, transparent: true, depthTest: false, depthWrite: false });
|
|
276
|
+
const object = new THREE.Mesh(new THREE.PlaneGeometry(2, 2), material);
|
|
277
|
+
object.frustumCulled = false;
|
|
278
|
+
object.renderOrder = 999;
|
|
279
|
+
object.name = "weather-heat-haze";
|
|
280
|
+
object.visible = false;
|
|
281
|
+
return {
|
|
282
|
+
object,
|
|
283
|
+
update(sample, time) {
|
|
284
|
+
uniforms.uHaze.value = sample.haze;
|
|
285
|
+
uniforms.uTime.value = time;
|
|
286
|
+
object.visible = sample.haze > 0;
|
|
287
|
+
},
|
|
288
|
+
dispose() {
|
|
289
|
+
object.geometry.dispose();
|
|
290
|
+
material.dispose();
|
|
291
|
+
}
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// src/lightning.ts
|
|
296
|
+
var LIGHTNING = { light: 3.2, background: [0.25, 0.27, 0.32], white: 0.12, skyColor: 3820650, groundColor: 723724 };
|
|
297
|
+
function createLightning(THREE, scene, vfx) {
|
|
298
|
+
const light = new THREE.HemisphereLight(LIGHTNING.skyColor, LIGHTNING.groundColor, 0);
|
|
299
|
+
light.name = "weather-lightning";
|
|
300
|
+
scene.add(light);
|
|
301
|
+
return {
|
|
302
|
+
light,
|
|
303
|
+
update(sample, background) {
|
|
304
|
+
const flash2 = sample.flash;
|
|
305
|
+
light.intensity = flash2 * LIGHTNING.light;
|
|
306
|
+
if (flash2 <= 0) return;
|
|
307
|
+
if (background) {
|
|
308
|
+
background.r += flash2 * LIGHTNING.background[0];
|
|
309
|
+
background.g += flash2 * LIGHTNING.background[1];
|
|
310
|
+
background.b += flash2 * LIGHTNING.background[2];
|
|
311
|
+
}
|
|
312
|
+
const screen2 = vfx?.workshop().screen;
|
|
313
|
+
if (screen2) screen2.white = Math.max(screen2.white, flash2 * LIGHTNING.white);
|
|
314
|
+
},
|
|
315
|
+
dispose() {
|
|
316
|
+
scene.remove(light);
|
|
317
|
+
light.dispose();
|
|
318
|
+
}
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// ../game-vfx/dist/index.js
|
|
323
|
+
var BYTE_MAX = 255;
|
|
324
|
+
var SRGB_LINEAR_SLOPE = 0.0773993808;
|
|
325
|
+
var SRGB_THRESHOLD = 0.04045;
|
|
326
|
+
function hexToRgb(hex) {
|
|
327
|
+
const whole = Math.floor(hex);
|
|
328
|
+
return [(whole >> 16 & BYTE_MAX) / BYTE_MAX, (whole >> 8 & BYTE_MAX) / BYTE_MAX, (whole & BYTE_MAX) / BYTE_MAX];
|
|
329
|
+
}
|
|
330
|
+
function srgbChannelToLinear(channel) {
|
|
331
|
+
return channel < SRGB_THRESHOLD ? channel * SRGB_LINEAR_SLOPE : Math.pow(channel * 0.9478672986 + 0.0521327014, 2.4);
|
|
332
|
+
}
|
|
333
|
+
function hexToLinearRgb(hex) {
|
|
334
|
+
const [red, green, blue] = hexToRgb(hex);
|
|
335
|
+
return [srgbChannelToLinear(red), srgbChannelToLinear(green), srgbChannelToLinear(blue)];
|
|
336
|
+
}
|
|
337
|
+
var SMOKE_COLORS = {
|
|
338
|
+
grey: hexToLinearRgb(6972767),
|
|
339
|
+
dark: hexToLinearRgb(4867136),
|
|
340
|
+
black: hexToLinearRgb(3814449),
|
|
341
|
+
brown: hexToLinearRgb(8019006),
|
|
342
|
+
dust: hexToLinearRgb(8221544),
|
|
343
|
+
concrete: hexToLinearRgb(9407106),
|
|
344
|
+
white: hexToLinearRgb(11841704),
|
|
345
|
+
blood: hexToLinearRgb(5901067),
|
|
346
|
+
bile: hexToLinearRgb(8030762),
|
|
347
|
+
gas: hexToLinearRgb(15265007)
|
|
348
|
+
};
|
|
349
|
+
var DEFAULT_COLOR = [85 / 255, 85 / 255, 85 / 255];
|
|
350
|
+
function createVec3(x = 0, y = 0, z = 0) {
|
|
351
|
+
return { x, y, z };
|
|
352
|
+
}
|
|
353
|
+
var call = (name) => (...args) => ({ $: name, a: args });
|
|
354
|
+
var rnd = call("rnd");
|
|
355
|
+
var rand = call("rand");
|
|
356
|
+
var add = call("add");
|
|
357
|
+
var concat = call("concat");
|
|
358
|
+
var sub = call("sub");
|
|
359
|
+
var mul = call("mul");
|
|
360
|
+
var div = call("div");
|
|
361
|
+
var mod = call("mod");
|
|
362
|
+
var neg = call("neg");
|
|
363
|
+
var abs = call("abs");
|
|
364
|
+
var sqrt = call("sqrt");
|
|
365
|
+
var exp = call("exp");
|
|
366
|
+
var sin = call("sin");
|
|
367
|
+
var cos = call("cos");
|
|
368
|
+
var atan2 = call("atan2");
|
|
369
|
+
var min = call("min");
|
|
370
|
+
var max = call("max");
|
|
371
|
+
var floor = call("floor");
|
|
372
|
+
var ceil = call("ceil");
|
|
373
|
+
var round = call("round");
|
|
374
|
+
var clamp = call("clamp");
|
|
375
|
+
var lerp2 = call("lerp");
|
|
376
|
+
var ease = call("ease");
|
|
377
|
+
var lt = call("lt");
|
|
378
|
+
var gt = call("gt");
|
|
379
|
+
var le = call("le");
|
|
380
|
+
var ge = call("ge");
|
|
381
|
+
var eq = call("eq");
|
|
382
|
+
var ne = call("ne");
|
|
383
|
+
var not = call("not");
|
|
384
|
+
var and = call("and");
|
|
385
|
+
var or = call("or");
|
|
386
|
+
var ite = call("ite");
|
|
387
|
+
var vadd = call("vadd");
|
|
388
|
+
var vsub = call("vsub");
|
|
389
|
+
var vscale = call("vscale");
|
|
390
|
+
var vnorm = call("vnorm");
|
|
391
|
+
var vneg = call("vneg");
|
|
392
|
+
var vlerp = call("vlerp");
|
|
393
|
+
var vx = call("vx");
|
|
394
|
+
var vy = call("vy");
|
|
395
|
+
var vz = call("vz");
|
|
396
|
+
var vdist = call("vdist");
|
|
397
|
+
var vwith = call("with");
|
|
398
|
+
var pick = call("at");
|
|
399
|
+
var scaled = call("scaled");
|
|
400
|
+
var param = (...values) => ({ $: "param", a: [values] });
|
|
401
|
+
var local = (name, value, body) => ({ $: "let", a: [name, value, body] });
|
|
402
|
+
var query = (behavior2, name, ...args) => ({ $: "query", a: [behavior2, name, ...args] });
|
|
403
|
+
var variable = (name) => ({ $: "var", a: [name] });
|
|
404
|
+
var cameraForward = call("cameraForward");
|
|
405
|
+
var TIME = { $: "t" };
|
|
406
|
+
var PARAM = { $: "paramIndex" };
|
|
407
|
+
var DELTA = { $: "dt" };
|
|
408
|
+
var INDEX = { $: "index" };
|
|
409
|
+
var QUALITY = { $: "quality" };
|
|
410
|
+
var FRESH = { $: "fresh" };
|
|
411
|
+
var DIRECTION = { $: "direction" };
|
|
412
|
+
var CAMERA_POSITION = { $: "cameraPosition" };
|
|
413
|
+
var burst = (system, count, spawn2) => ({ op: "burst", system, count, spawn: spawn2 });
|
|
414
|
+
var spawn = (system, options) => ({ op: "spawn", system, spawn: options });
|
|
415
|
+
var emit = (key, system, rate, options) => ({ op: "emit", key, system, rate, spawn: options });
|
|
416
|
+
var mesh = (options) => ({ op: "mesh", spawn: options });
|
|
417
|
+
var debris = (options) => ({ op: "debris", spawn: options });
|
|
418
|
+
var decal = (...args) => ({ op: "decal", args });
|
|
419
|
+
var ring = (...args) => ({ op: "ring", args });
|
|
420
|
+
var flash = (...args) => ({ op: "flash", args });
|
|
421
|
+
var lens = (...args) => ({ op: "lens", args });
|
|
422
|
+
var screen = (change) => ({ op: "screen", ...change });
|
|
423
|
+
var fireLight = (slot, point, intensity, time) => ({ op: "fire_light", slot, point, intensity, time });
|
|
424
|
+
var fireLightOff = (slot) => ({ op: "fire_light_off", slot });
|
|
425
|
+
var cue = (name, args, draws) => ({ op: "cue", cue: name, ...args !== void 0 ? { args } : {}, ...draws !== void 0 ? { draws } : {} });
|
|
426
|
+
var call2 = (macro, ...args) => ({ op: "call", macro, args });
|
|
427
|
+
var after = (time, ...steps) => ({ op: "at", time, steps });
|
|
428
|
+
var when = (condition, steps, otherwise) => ({ op: "when", if: condition, steps, ...otherwise ? { otherwise } : {} });
|
|
429
|
+
var repeat = (count, ...steps) => ({ op: "repeat", count, steps });
|
|
430
|
+
var set = (name, value) => ({ op: "set", name, value });
|
|
431
|
+
var behavior = (id, action, args) => ({ op: "behavior", id, action, ...args !== void 0 ? { args } : {} });
|
|
432
|
+
var append = (name, value) => ({ op: "append", name, value });
|
|
433
|
+
var camera = (eye, target, instant) => ({ op: "camera", eye, target, ...instant ? { instant } : {} });
|
|
434
|
+
var post = (values) => ({ op: "post", values });
|
|
435
|
+
var CENTRE = [0, 1.1, 0];
|
|
436
|
+
var UP = [0, 1, 0];
|
|
437
|
+
var BLOATER_CLOUD = {
|
|
438
|
+
id: "bloater_cloud",
|
|
439
|
+
pageId: "inchado",
|
|
440
|
+
team: "creatures",
|
|
441
|
+
budget: { particles: 180 },
|
|
442
|
+
loop: 9,
|
|
443
|
+
view: { eye: [5.5, 3.2, 6], target: [0, 1, 0] },
|
|
444
|
+
timeline: [
|
|
445
|
+
after(
|
|
446
|
+
1,
|
|
447
|
+
burst("normal", 40, { p: CENTRE, r: 0.4, sp: [1.5, 4], drag: 2.2, life: [4, 6], size: [1, 2.2], grow: 2, c0: 7309884, c1: 3885606, a: 0.32, fi: 0.08, g: 0.05 }),
|
|
448
|
+
burst("normal", 30, { p: CENTRE, dir: UP, cone: 1.3, sp: [2, 4], life: 1.4, size: [0.04, 0.08], c0: 4872732, g: 9.8, fi: 0, gnd: 3, ds: [0.1, 0.2] }),
|
|
449
|
+
repeat(scaled(10), debris({ p: CENTRE, dir: UP, cone: 1.2, sp: [2, 5], size: [0.07, 0.05, 0.07], k: [0.6, 1.4], c: ite(mod(INDEX, 2), 7043666, 4856338), life: 9 })),
|
|
450
|
+
decal(0, 0, 0, 1.6, 6978084, { grow: 0.6, life: 60, fluid: "bile" }),
|
|
451
|
+
ring([0, 0.02, 0], 4, 4, 8, 3824160, UP, 0.35),
|
|
452
|
+
screen({ add: { shake: 0.15 } })
|
|
453
|
+
)
|
|
454
|
+
],
|
|
455
|
+
tick: [
|
|
456
|
+
when(and(gt(TIME, 1), lt(TIME, 8)), [
|
|
457
|
+
emit("gas", "normal", 7, { p: [0, 0.4, 0], r: 3.4, flat: true, dir: UP, cone: 1.3, sp: [0.1, 0.35], drag: 0.4, life: [3, 5], size: [1.2, 2.2], grow: 1.5, c0: 7309884, c1: 3885606, a: 0.22, fi: 0.3 }),
|
|
458
|
+
emit("mote", "add", 10, { p: [0, 0.6, 0], r: 3.6, flat: true, dir: UP, cone: 0.6, sp: [0.05, 0.25], life: [1.5, 2.5], size: [0.04, 0.07], c0: 6283402, a: 0.7, fi: 0.4 })
|
|
459
|
+
])
|
|
460
|
+
]
|
|
461
|
+
};
|
|
462
|
+
var BLOOD = param(9046538, 5901328, 3808274, 1906964);
|
|
463
|
+
var BLEED = [1, 0.7, 0.35];
|
|
464
|
+
var BLOOD_HIT = {
|
|
465
|
+
id: "blood_hit",
|
|
466
|
+
pageId: "sangue",
|
|
467
|
+
team: "creatures",
|
|
468
|
+
params: { id: "age", options: ["fresh", "recent", "old", "decrepit"], default: 0 },
|
|
469
|
+
budget: { particles: 70, decals: 1 },
|
|
470
|
+
loop: 3.2,
|
|
471
|
+
view: { eye: [2.6, 1.9, 3.4], target: [0, 1, -0.6] },
|
|
472
|
+
timeline: [
|
|
473
|
+
after(0.3, call2("blood_hit", [0, 1.3, 0.1], vnorm([0.15, 0.1, -1]), PARAM)),
|
|
474
|
+
after(1.5, call2("blood_hit", [0.1, 1.05, 0.1], vnorm([-0.2, 0.05, -1]), PARAM, 0.8)),
|
|
475
|
+
when(lt(PARAM, 3), [after(0.7, decal(0, 0, -0.2, add(0.5, mul(0.7, pick(BLEED, PARAM))), BLOOD, { grow: add(2, mul(2, pick(BLEED, PARAM))), dark: 60, dry: 3874068 }))])
|
|
476
|
+
],
|
|
477
|
+
tick: [
|
|
478
|
+
when(and(lt(PARAM, 2), gt(TIME, 0.3)), [
|
|
479
|
+
emit("drip", "normal", param(7, 3), {
|
|
480
|
+
p: [0.05, 1.15, 0.17],
|
|
481
|
+
box: [0.08, 0.05, 0],
|
|
482
|
+
dir: [0, 1, 0],
|
|
483
|
+
cone: 0.2,
|
|
484
|
+
sp: [0, 0.2],
|
|
485
|
+
life: 1.2,
|
|
486
|
+
size: 0.03,
|
|
487
|
+
c0: BLOOD,
|
|
488
|
+
g: 9.8,
|
|
489
|
+
fi: 0,
|
|
490
|
+
gnd: 3,
|
|
491
|
+
ds: [0.04, 0.08]
|
|
492
|
+
})
|
|
493
|
+
])
|
|
494
|
+
]
|
|
495
|
+
};
|
|
496
|
+
var UP2 = [0, 1, 0];
|
|
497
|
+
var CORPSE_DECAY = {
|
|
498
|
+
id: "corpse_decay",
|
|
499
|
+
pageId: "corpo",
|
|
500
|
+
team: "creatures",
|
|
501
|
+
budget: { particles: 40 },
|
|
502
|
+
loop: 8.5,
|
|
503
|
+
view: { eye: [2.4, 1.6, 2.6], target: [0, 0.3, -0.6] },
|
|
504
|
+
timeline: [after(0.8, decal(0, 0, -0.9, 1.1, 5901328, { grow: 1.5, dark: 5, dry: 3874068 }))],
|
|
505
|
+
tick: [
|
|
506
|
+
when(and(gt(TIME, 2.5), lt(TIME, 7)), [
|
|
507
|
+
emit("fly", "normal", 6, { p: [0, 0.35, -0.8], r: 0.5, sp: [0.3, 0.8], life: [0.6, 1.2], size: 0.02, c0: 328965, a: 1, fi: 0.2 })
|
|
508
|
+
]),
|
|
509
|
+
when(and(gt(TIME, 6.8), lt(TIME, 7.6)), [
|
|
510
|
+
emit("dust", "normal", 40, { p: [0, 0.15, -0.8], box: [0.25, 0.05, 0.8], dir: UP2, cone: 0.6, sp: [0.2, 0.6], drag: 1, life: [1, 1.8], size: [0.12, 0.22], grow: 3, c0: 2828066, a: 0.5 })
|
|
511
|
+
])
|
|
512
|
+
]
|
|
513
|
+
};
|
|
514
|
+
var RUNNERS = [false, true, false, false, false, true, false, false, false, true];
|
|
515
|
+
var RUN_SPEED = 3.8;
|
|
516
|
+
var WALK_SPEED = 0.7;
|
|
517
|
+
var SPEED = ite(pick(RUNNERS, INDEX), RUN_SPEED, WALK_SPEED);
|
|
518
|
+
var walkTo = behavior("walkers", "walk", { index: INDEX, to: [-12, 0, query("walkers", "z", INDEX)], speed: SPEED });
|
|
519
|
+
var EYES_IN_FOG = {
|
|
520
|
+
id: "eyes_in_fog",
|
|
521
|
+
pageId: "olhos",
|
|
522
|
+
team: "creatures",
|
|
523
|
+
budget: { particles: 20 },
|
|
524
|
+
loop: 0,
|
|
525
|
+
view: { eye: [-9, 1.7, 2], target: [6, 1.3, 2] },
|
|
526
|
+
setup: [
|
|
527
|
+
repeat(10, set("placeX", rnd(4, 34)), set("placeZ", rnd(-1.5, 5.5)), behavior("walkers", "place", { index: INDEX, x: variable("placeX"), z: variable("placeZ"), facing: -Math.PI / 2 }), walkTo)
|
|
528
|
+
],
|
|
529
|
+
timeline: [],
|
|
530
|
+
tick: [
|
|
531
|
+
repeat(
|
|
532
|
+
10,
|
|
533
|
+
when(lt(query("walkers", "x", INDEX), -8), [behavior("walkers", "move_x", { index: INDEX, x: rnd(28, 36) }), walkTo], [when(not(query("walkers", "is_walking", INDEX)), [walkTo])]),
|
|
534
|
+
when(and(pick(RUNNERS, INDEX), lt(QUALITY, 2)), [
|
|
535
|
+
spawn("streak", { p: query("walkers", "point", INDEX, [0, 1.74, 0.2]), dir: [1, 0, 0], cone: 0, sp: RUN_SPEED, v: [-RUN_SPEED, 0, 0], life: 0.25, len: 0.06, c0: 15022379, c1: 4194304, a: 0.8 })
|
|
536
|
+
])
|
|
537
|
+
)
|
|
538
|
+
]
|
|
539
|
+
};
|
|
540
|
+
var SHOULDER = [0.36, 1.46, 0.05];
|
|
541
|
+
var FRESH_BLOOD = 9046538;
|
|
542
|
+
var DISMEMBER = {
|
|
543
|
+
id: "dismember",
|
|
544
|
+
pageId: "membro",
|
|
545
|
+
team: "creatures",
|
|
546
|
+
budget: { particles: 60, debris: 1, decals: 4 },
|
|
547
|
+
loop: 3.6,
|
|
548
|
+
view: { eye: [3, 1.8, 2.2], target: [0.4, 1.1, 0] },
|
|
549
|
+
timeline: [
|
|
550
|
+
after(
|
|
551
|
+
0.4,
|
|
552
|
+
debris({ p: SHOULDER, v: [2.2, 2.5, -0.6], sp: 0, size: [0.12, 0.12, 0.66], c: 7174746, spin: 9, life: 12, bounce: 0.25 }),
|
|
553
|
+
burst("normal", 12, { p: SHOULDER, r: 0.05, sp: [0.3, 1.2], drag: 3, life: [0.3, 0.6], size: [0.1, 0.16], grow: 3, c0: FRESH_BLOOD, a: 0.6 })
|
|
554
|
+
)
|
|
555
|
+
],
|
|
556
|
+
tick: [
|
|
557
|
+
when(and(gt(TIME, 0.4), lt(TIME, 1.1)), [
|
|
558
|
+
emit("jet", "normal", mul(90, ite(gt(sin(mul(sub(TIME, 0.4), 28)), 0), 1, 0.2)), { p: SHOULDER, dir: vnorm([1, 0.35, 0.1]), cone: 0.25, sp: [1.5, 3], life: 1.4, size: [0.03, 0.055], c0: FRESH_BLOOD, g: 9.8, fi: 0, gnd: 3, ds: [0.05, 0.12] })
|
|
559
|
+
])
|
|
560
|
+
]
|
|
561
|
+
};
|
|
562
|
+
var FRESH_BLOOD2 = 9046538;
|
|
563
|
+
var HEADSHOT = {
|
|
564
|
+
id: "headshot",
|
|
565
|
+
pageId: "headshot",
|
|
566
|
+
team: "creatures",
|
|
567
|
+
budget: { particles: 70, debris: 8, decals: 1 },
|
|
568
|
+
loop: 3.2,
|
|
569
|
+
view: { eye: [2.2, 1.8, 3], target: [0, 1.2, -0.5] },
|
|
570
|
+
timeline: [
|
|
571
|
+
after(
|
|
572
|
+
0.45,
|
|
573
|
+
burst("normal", 20, { p: [0, 1.7, 0], r: 0.1, sp: [0.4, 1.8], drag: 3, life: [0.4, 0.75], size: [0.12, 0.2], grow: 3, c0: FRESH_BLOOD2, a: 0.7 }),
|
|
574
|
+
burst("normal", 35, { p: [0, 1.7, 0], dir: vnorm([0, 0.45, -1]), cone: 0.8, sp: [2, 5], life: 1.5, size: [0.035, 0.065], c0: FRESH_BLOOD2, g: 9.8, fi: 0, gnd: 3, ds: [0.06, 0.14] }),
|
|
575
|
+
repeat(scaled(8), debris({ p: [0, 1.7, 0], dir: vnorm([0, 0.6, -1]), cone: 0.9, sp: [1.5, 4], size: [0.06, 0.05, 0.06], k: [0.5, 1.2], c: ite(mod(INDEX, 2), 14274495, 7174746), life: 8 })),
|
|
576
|
+
flash([0, 1.7, 0], 16724e3, 1.2, 0.08, 4)
|
|
577
|
+
),
|
|
578
|
+
after(1.4, decal(0, 0, -1.5, 0.9, FRESH_BLOOD2, { grow: 2.4, dark: 60, dry: 3874068 }))
|
|
579
|
+
]
|
|
580
|
+
};
|
|
581
|
+
var UP3 = [0, 1, 0];
|
|
582
|
+
var REANIMATION = {
|
|
583
|
+
id: "reanimation",
|
|
584
|
+
pageId: "reanima",
|
|
585
|
+
team: "creatures",
|
|
586
|
+
budget: { particles: 30 },
|
|
587
|
+
loop: 6.5,
|
|
588
|
+
view: { eye: [2.4, 1.4, 2.4], target: [0, 0.6, -0.4] },
|
|
589
|
+
timeline: [],
|
|
590
|
+
tick: [
|
|
591
|
+
when(lt(TIME, 3.4), [
|
|
592
|
+
when(gt(TIME, 1), [cue("zombie_arm_twitch", void 0, 2)]),
|
|
593
|
+
when(gt(TIME, 0.6), [
|
|
594
|
+
emit("mote", "add", 8, { p: [0, 0.2, -0.8], box: [0.25, 0.05, 0.6], dir: UP3, cone: 0.4, sp: [0.2, 0.5], life: [0.6, 1], size: [0.03, 0.05], c0: 10469978, a: 0.7, fi: 0.3 })
|
|
595
|
+
])
|
|
596
|
+
]),
|
|
597
|
+
when(and(gt(TIME, 5), lt(TIME, 5.6)), [
|
|
598
|
+
emit("br", "normal", 20, { p: [0, 1.68, 0.2], dir: vnorm([0, 0.3, 1]), cone: 0.3, sp: [0.6, 1.1], drag: 1.5, life: 1.2, size: [0.05, 0.1], grow: 5, c0: 14212578, a: 0.2 })
|
|
599
|
+
])
|
|
600
|
+
]
|
|
601
|
+
};
|
|
602
|
+
var WHITE_RING = 15262416;
|
|
603
|
+
var PREPARATION_END = 1.7;
|
|
604
|
+
var SHRIEK_END = 2.6;
|
|
605
|
+
var SCREAMER_SHRIEK = {
|
|
606
|
+
id: "screamer_shriek",
|
|
607
|
+
pageId: "grito",
|
|
608
|
+
team: "creatures",
|
|
609
|
+
budget: { particles: 150 },
|
|
610
|
+
loop: 5,
|
|
611
|
+
view: { eye: [6, 3, 7], target: [0, 1, -1] },
|
|
612
|
+
timeline: [
|
|
613
|
+
after(
|
|
614
|
+
PREPARATION_END,
|
|
615
|
+
repeat(3, after(add(PREPARATION_END, mul(INDEX, 0.18)), ring([0, 0.03, 0], 0.3, 9, 0.9, WHITE_RING))),
|
|
616
|
+
screen({ add: { chroma: 7, shake: 0.25 } })
|
|
617
|
+
)
|
|
618
|
+
],
|
|
619
|
+
tick: [
|
|
620
|
+
when(lt(TIME, PREPARATION_END), [
|
|
621
|
+
emit("vap", "normal", 18, { p: [0, 1.68, 0.2], dir: vnorm([0, 0.5, 1]), cone: 0.3, sp: [0.6, 1.2], drag: 1.5, life: [0.8, 1.3], size: [0.05, 0.1], grow: 5, c0: 14212578, a: 0.2 })
|
|
622
|
+
], [
|
|
623
|
+
when(lt(TIME, SHRIEK_END), [
|
|
624
|
+
set("shriekRadius", mul(div(sub(TIME, PREPARATION_END), 0.9), 8)),
|
|
625
|
+
emit(
|
|
626
|
+
"dust",
|
|
627
|
+
"normal",
|
|
628
|
+
140,
|
|
629
|
+
local("angle", mul(rand(), 6.283), {
|
|
630
|
+
p: [mul(cos(variable("angle")), variable("shriekRadius")), 0.05, mul(sin(variable("angle")), variable("shriekRadius"))],
|
|
631
|
+
dir: vnorm([cos(variable("angle")), 0.6, sin(variable("angle"))]),
|
|
632
|
+
cone: 0.3,
|
|
633
|
+
sp: [0.6, 1.6],
|
|
634
|
+
drag: 2,
|
|
635
|
+
life: [0.8, 1.4],
|
|
636
|
+
size: [0.2, 0.35],
|
|
637
|
+
grow: 3,
|
|
638
|
+
c0: 6117197,
|
|
639
|
+
a: 0.35
|
|
640
|
+
})
|
|
641
|
+
)
|
|
642
|
+
])
|
|
643
|
+
])
|
|
644
|
+
]
|
|
645
|
+
};
|
|
646
|
+
function localToWorld(translation, rotation, local2) {
|
|
647
|
+
const [x, y, z] = local2;
|
|
648
|
+
const [a, c, e] = [Math.cos(rotation[0]), Math.cos(rotation[1]), Math.cos(rotation[2])];
|
|
649
|
+
const [b, d, f] = [Math.sin(rotation[0]), Math.sin(rotation[1]), Math.sin(rotation[2])];
|
|
650
|
+
const [ae, af, be, bf] = [a * e, a * f, b * e, b * f];
|
|
651
|
+
return [
|
|
652
|
+
c * e * x + -c * f * y + d * z + translation[0],
|
|
653
|
+
(af + be * d) * x + (ae - bf * d) * y + -b * c * z + translation[1],
|
|
654
|
+
(bf - ae * d) * x + (be + af * d) * y + a * c * z + translation[2]
|
|
655
|
+
];
|
|
656
|
+
}
|
|
657
|
+
var MATERIALS = ["concrete", "metal", "wood", "glass", "flesh", "water"];
|
|
658
|
+
var CAR_ORIGIN = [5.6, 0, 0.8];
|
|
659
|
+
var CAR_ROTATION = [0, -0.4, 0];
|
|
660
|
+
var FACING_WALL = [0, 0, 1];
|
|
661
|
+
var UP4 = [0, 1, 0];
|
|
662
|
+
var GLASS = 3;
|
|
663
|
+
var FLESH = 4;
|
|
664
|
+
var WATER = 5;
|
|
665
|
+
var SHOT_TIMES = [0, 0.55, 1.1];
|
|
666
|
+
var LAST_SHOT = 2;
|
|
667
|
+
var BUMPER = localToWorld(CAR_ORIGIN, CAR_ROTATION, [0.96, 0.7, 0.4]);
|
|
668
|
+
var CAR_SIDE = [Math.cos(CAR_ROTATION[1]), 0, -Math.sin(CAR_ROTATION[1])];
|
|
669
|
+
var POINTS = [[-2, 1.6, -4.45], BUMPER, [2, 1.3, -4.36], [-5, 1.9, -4.45], [0, 1.25, 0.16], [-1.5, 0.012, 2.2]];
|
|
670
|
+
var NORMALS = [FACING_WALL, CAR_SIDE, FACING_WALL, FACING_WALL, FACING_WALL, UP4];
|
|
671
|
+
var EYES = [[-2, 1.6, -1.8], localToWorld(CAR_ORIGIN, CAR_ROTATION, [3, 1.4, 1.5]), [2, 1.3, -1.6], [-5, 1.9, -1.8], [0, 1.2, 2.6], [-1.5, 0.8, 4.6]];
|
|
672
|
+
var WINDOW = { centreX: -5, centreY: 1.9, width: 2.6, height: 1.8, pixelsX: 256, pixelsY: 180 };
|
|
673
|
+
var scatter = ite(eq(PARAM, WATER), [rnd(-0.6, 0.6), 0, rnd(-0.3, 0.3)], ite(eq(PARAM, FLESH), [rnd(-0.1, 0.1), rnd(-0.15, 0.15), 0], [rnd(-0.4, 0.4), rnd(-0.3, 0.3), 0]));
|
|
674
|
+
var hitX = { $: "vx", a: [variable("hit")] };
|
|
675
|
+
var hitY = { $: "vy", a: [variable("hit")] };
|
|
676
|
+
var pixelX = { $: "mul", a: [{ $: "add", a: [{ $: "div", a: [{ $: "sub", a: [hitX, WINDOW.centreX] }, WINDOW.width] }, 0.5] }, WINDOW.pixelsX] };
|
|
677
|
+
var pixelY = { $: "mul", a: [{ $: "sub", a: [1, { $: "add", a: [{ $: "div", a: [{ $: "sub", a: [hitY, WINDOW.centreY] }, WINDOW.height] }, 0.5] }] }, WINDOW.pixelsY] };
|
|
678
|
+
var IMPACT_BY_MATERIAL = {
|
|
679
|
+
id: "impact",
|
|
680
|
+
pageId: "impacto",
|
|
681
|
+
team: "weapons",
|
|
682
|
+
params: { id: "material", options: MATERIALS, default: 0 },
|
|
683
|
+
budget: { particles: 40, decals: 1 },
|
|
684
|
+
loop: 2.6,
|
|
685
|
+
view: { eye: [0, 1.8, 4.5], target: [0, 1.2, -2] },
|
|
686
|
+
props: ["cracks"],
|
|
687
|
+
timeline: [
|
|
688
|
+
when({ $: "eq", a: [PARAM, WATER] }, [decal(-1.5, 0, 2.2, 3.2, 856600, { grow: 0, life: 60, ar: 0.55 })]),
|
|
689
|
+
repeat(
|
|
690
|
+
SHOT_TIMES.length,
|
|
691
|
+
after(
|
|
692
|
+
add(0.2, pick(SHOT_TIMES, INDEX)),
|
|
693
|
+
set("hit", vadd(pick(POINTS, PARAM), scatter)),
|
|
694
|
+
call2("impact", pick(MATERIALS, PARAM), variable("hit"), pick(NORMALS, PARAM), 1, 0),
|
|
695
|
+
when(eq(PARAM, GLASS), [behavior("cracks", "crack", { x: pixelX, y: pixelY, big: eq(INDEX, LAST_SHOT) })])
|
|
696
|
+
)
|
|
697
|
+
),
|
|
698
|
+
when(FRESH, [camera(pick(EYES, PARAM), pick(POINTS, PARAM))])
|
|
699
|
+
]
|
|
700
|
+
};
|
|
701
|
+
var BLOOD2 = [9046538, 5901328, 3808274, 1906964];
|
|
702
|
+
var BODY_Z = [2.2, 1, -0.2, -1.4, -2.6];
|
|
703
|
+
var MUZZLE_Z = 8.5;
|
|
704
|
+
var SPEED2 = 12;
|
|
705
|
+
var WALL_Z = -4.4;
|
|
706
|
+
var FORWARD = [0, 0, -1];
|
|
707
|
+
var bulletAt = [0, 1.45, variable("bulletZ")];
|
|
708
|
+
var PENETRATION = {
|
|
709
|
+
id: "penetration",
|
|
710
|
+
pageId: "penetra",
|
|
711
|
+
team: "weapons",
|
|
712
|
+
budget: { particles: 250 },
|
|
713
|
+
loop: 4.2,
|
|
714
|
+
view: { eye: [4.2, 2.2, 6.5], target: [0, 1.2, -0.5] },
|
|
715
|
+
setup: [
|
|
716
|
+
cue("zombie_visible", { index: -1, visible: false }),
|
|
717
|
+
repeat(
|
|
718
|
+
BODY_Z.length,
|
|
719
|
+
set("bodyX", rnd(-0.05, 0.05)),
|
|
720
|
+
set("bodyTurn", rnd(-0.3, 0.3)),
|
|
721
|
+
append("bodiesX", variable("bodyX")),
|
|
722
|
+
cue("zombie_place", { index: INDEX, x: variable("bodyX"), z: pick(BODY_Z, INDEX), turn: variable("bodyTurn") })
|
|
723
|
+
)
|
|
724
|
+
],
|
|
725
|
+
timeline: [set("bulletZ", MUZZLE_Z), set("bulletOn", true), call2("muzzle", "barrett", [0, 1.45, MUZZLE_Z], FORWARD)],
|
|
726
|
+
tick: [
|
|
727
|
+
when(variable("bulletOn"), [
|
|
728
|
+
set("previousZ", variable("bulletZ")),
|
|
729
|
+
set("bulletZ", sub(variable("bulletZ"), mul(SPEED2, DELTA))),
|
|
730
|
+
spawn("streak", { p: bulletAt, dir: FORWARD, cone: 0, sp: 12, life: 0.04, len: 0.07, c0: 16765072 }),
|
|
731
|
+
spawn("add", { p: bulletAt, size: 0.09, life: 0.05, c0: 16760944, fi: 0 }),
|
|
732
|
+
spawn("normal", { p: bulletAt, r: 0.02, sp: [0, 0.05], life: [1.2, 2], size: 0.05, grow: 3, c0: 13159634, a: 0.12, fi: 0.1 }),
|
|
733
|
+
repeat(
|
|
734
|
+
BODY_Z.length,
|
|
735
|
+
when(and(gt(variable("previousZ"), pick(BODY_Z, INDEX)), le(variable("bulletZ"), pick(BODY_Z, INDEX))), [
|
|
736
|
+
call2("blood_hit", [0, 1.45, sub(pick(BODY_Z, INDEX), 0.1)], [0, 0.05, -1], mod(INDEX, 4), 0.8),
|
|
737
|
+
cue("zombie_fall", { index: INDEX, delay: 0.05, duration: 0.6 }),
|
|
738
|
+
after(
|
|
739
|
+
add(TIME, 0.6),
|
|
740
|
+
decal(pick(variable("bodiesX"), INDEX), 0, sub(pick(BODY_Z, INDEX), 1.2), 0.6, pick(BLOOD2, mod(INDEX, 4)), { grow: 2, dark: 60, dry: 3874068 })
|
|
741
|
+
)
|
|
742
|
+
])
|
|
743
|
+
),
|
|
744
|
+
when(lt(variable("bulletZ"), WALL_Z), [set("bulletOn", false), call2("impact", "concrete", [0, 1.45, -4.45], [0, 0, 1], 2.2)])
|
|
745
|
+
])
|
|
746
|
+
]
|
|
747
|
+
};
|
|
748
|
+
var TIP = [-0.8, 1.38, 3.4 - 0.78];
|
|
749
|
+
var PORT = [-0.76, 1.4, 3.32];
|
|
750
|
+
var FORWARD2 = [0, 0, -1];
|
|
751
|
+
var UP5 = [0, 1, 0];
|
|
752
|
+
var BURST_SHOTS = 12;
|
|
753
|
+
var CASINGS_AND_MAGAZINE = {
|
|
754
|
+
id: "casings_and_magazine",
|
|
755
|
+
pageId: "capsulas",
|
|
756
|
+
team: "weapons",
|
|
757
|
+
budget: { particles: 200, debris: 13 },
|
|
758
|
+
loop: 4.6,
|
|
759
|
+
view: { eye: [0.9, 1.3, 4.6], target: [-0.6, 0.6, 3.1] },
|
|
760
|
+
setup: [cue("gun_visible", { visible: true }), cue("zombie_visible", { index: -1, visible: false })],
|
|
761
|
+
timeline: [
|
|
762
|
+
repeat(
|
|
763
|
+
BURST_SHOTS,
|
|
764
|
+
after(add(0.2, mul(INDEX, 0.1)), call2("muzzle", "ak", TIP, FORWARD2), call2("casing", PORT, ""), cue("gun_recoil", { kick: 0.05 }))
|
|
765
|
+
),
|
|
766
|
+
after(1.8, debris({ p: [-0.8, 1.15, 3.3], v: [0.1, -0.5, 0.1], sp: 0, size: [0.05, 0.2, 0.09], c: 2763306, spin: 3, life: 20, bounce: 0.2 }))
|
|
767
|
+
],
|
|
768
|
+
tick: [
|
|
769
|
+
when(and(gt(TIME, 1.4), lt(TIME, 3.6)), [
|
|
770
|
+
emit("hot", "normal", 10, { p: TIP, dir: UP5, cone: 0.25, sp: [0.2, 0.5], life: [1.4, 2.2], size: [0.03, 0.06], grow: 5, c0: 10132118, a: 0.18, g: -0.2, fi: 0.2 })
|
|
771
|
+
])
|
|
772
|
+
]
|
|
773
|
+
};
|
|
774
|
+
var FROM = [-4, 1.6, 5];
|
|
775
|
+
var TARGET = [0, 0, -0.5];
|
|
776
|
+
var UP6 = [0, 1, 0];
|
|
777
|
+
var FLIGHT = 1;
|
|
778
|
+
var ARC_HEIGHT = 2.2;
|
|
779
|
+
var GLASS_GREEN = 3828282;
|
|
780
|
+
var OBJECT_ID_DRAWS = 12;
|
|
781
|
+
var at = (offset) => vadd(TARGET, offset);
|
|
782
|
+
var MOLOTOV = {
|
|
783
|
+
id: "molotov",
|
|
784
|
+
pageId: "molotov",
|
|
785
|
+
team: "weapons",
|
|
786
|
+
lab: "molotov",
|
|
787
|
+
budget: { particles: 300, lights: 1 },
|
|
788
|
+
loop: 9.5,
|
|
789
|
+
view: { eye: [5, 3, 6.5], target: [0, 0.6, -0.5] },
|
|
790
|
+
// three.js draws 12 random numbers (the object ids of the bottle's geometry, material and mesh) the first time the page builds the bottle
|
|
791
|
+
setup: [cue("zombie_visible", { index: -1, visible: false }), when(FRESH, [cue("prop_created", { prop: "bottle" }, OBJECT_ID_DRAWS)])],
|
|
792
|
+
timeline: [set("landed", false), cue("bottle_visible", { visible: true })],
|
|
793
|
+
tick: [
|
|
794
|
+
when(lt(TIME, FLIGHT), [
|
|
795
|
+
set("bottle", vwith(vlerp(FROM, TARGET, TIME), 1, add(lerp2(FROM[1], TARGET[1], TIME), mul(sin(mul(TIME, Math.PI)), ARC_HEIGHT)))),
|
|
796
|
+
cue("bottle_move", { position: variable("bottle"), spin: mul(10, DELTA) }),
|
|
797
|
+
emit("wick", "add", 40, { p: vadd(variable("bottle"), [0, 0.12, 0]), r: 0.03, sp: [0.1, 0.3], life: [0.15, 0.3], size: [0.08, 0.14], grow: 0.5, c0: 16765562, c1: 16732176, fi: 0, g: -1 }),
|
|
798
|
+
emit("wsm", "normal", 14, { p: variable("bottle"), size: [0.06, 0.1], grow: 4, life: [0.8, 1.2], c0: 3814704, a: 0.3, sp: [0, 0.2] })
|
|
799
|
+
], [
|
|
800
|
+
when(not(variable("landed")), [
|
|
801
|
+
set("landed", true),
|
|
802
|
+
cue("bottle_visible", { visible: false }),
|
|
803
|
+
repeat(scaled(12), debris({ p: at([0, 0.1, 0]), dir: UP6, cone: 1.3, sp: [1, 3], size: [0.04, 0.01, 0.04], c: GLASS_GREEN, life: 12 })),
|
|
804
|
+
burst("add", 45, { p: at([0, 0.15, 0]), dir: UP6, cone: 1.35, sp: [2, 4], drag: 2, life: [0.3, 0.6], size: [0.3, 0.5], c0: 16765562, c1: 10493960, fi: 0.05 }),
|
|
805
|
+
flash(at([0, 0.6, 0]), 16747056, 6, 0.3, 12, true),
|
|
806
|
+
decal(TARGET[0], 0, TARGET[2], 4.2, 854793, { grow: 0.8, life: 60 })
|
|
807
|
+
])
|
|
808
|
+
]),
|
|
809
|
+
when(and(gt(TIME, FLIGHT), lt(TIME, 8.2)), [
|
|
810
|
+
set("poolRadius", min(2.2, add(0.5, mul(sub(TIME, 1), 2.1)))),
|
|
811
|
+
set("poolFade", ite(gt(TIME, 7), max(0.1, sub(1, div(sub(TIME, 7), 1.2))), 1)),
|
|
812
|
+
call2("fire_emit", "mol", at([0, 0.05, 0]), variable("poolRadius"), mul(1.6, variable("poolFade")), { smoke: 16 }),
|
|
813
|
+
fireLight(0, at([0, 1, 0]), mul(3.2, variable("poolFade")), TIME)
|
|
814
|
+
], [
|
|
815
|
+
when(ge(TIME, 8.2), [
|
|
816
|
+
fireLightOff(0),
|
|
817
|
+
emit("emb", "add", 6, { p: TARGET, r: 2, flat: true, size: [0.04, 0.07], life: [0.6, 1.2], c0: 16738848, a: 0.8, fi: 0.3 })
|
|
818
|
+
])
|
|
819
|
+
])
|
|
820
|
+
]
|
|
821
|
+
};
|
|
822
|
+
var BODIES = [[1.6, 0.8], [-1.8, 1.2], [0.6, -2], [-1, -1.8], [2.4, -1.2]];
|
|
823
|
+
var BODY_X = BODIES.map(([x]) => x);
|
|
824
|
+
var BODY_Z2 = BODIES.map(([, z]) => z);
|
|
825
|
+
var FACING = BODIES.map(([x, z]) => Math.atan2(-x, -z));
|
|
826
|
+
var FUSE = 1.8;
|
|
827
|
+
var GRAVITY = 9.8;
|
|
828
|
+
var FLOOR = 0.07;
|
|
829
|
+
var BOUNCE = -0.4;
|
|
830
|
+
var SIDE_LOSS = 0.5;
|
|
831
|
+
var GRENADE = {
|
|
832
|
+
id: "grenade",
|
|
833
|
+
pageId: "granada",
|
|
834
|
+
team: "weapons",
|
|
835
|
+
lab: "m67",
|
|
836
|
+
budget: { particles: 400, debris: 16, decals: 1 },
|
|
837
|
+
loop: 6.5,
|
|
838
|
+
view: { eye: [7, 3.4, 7.5], target: [0, 0.8, -0.2] },
|
|
839
|
+
setup: [
|
|
840
|
+
cue("zombie_visible", { index: -1, visible: false }),
|
|
841
|
+
// three.js draws 12 random numbers (the object ids of the grenade's geometry, material and mesh) the first time the page builds it
|
|
842
|
+
when(FRESH, [cue("prop_created", { prop: "grenade" }, 12)]),
|
|
843
|
+
repeat(BODIES.length, cue("zombie_place", { index: INDEX, x: pick(BODY_X, INDEX), z: pick(BODY_Z2, INDEX), turn: pick(FACING, INDEX) }))
|
|
844
|
+
],
|
|
845
|
+
timeline: [
|
|
846
|
+
set("px", -4),
|
|
847
|
+
set("py", 1.4),
|
|
848
|
+
set("pz", 4.5),
|
|
849
|
+
set("vx", 3.2),
|
|
850
|
+
set("vy", 2.4),
|
|
851
|
+
set("vz", -3.6),
|
|
852
|
+
set("boom", false),
|
|
853
|
+
cue("grenade_visible", { visible: true })
|
|
854
|
+
],
|
|
855
|
+
tick: [
|
|
856
|
+
when(lt(TIME, FUSE), [
|
|
857
|
+
set("vy", sub(variable("vy"), mul(GRAVITY, DELTA))),
|
|
858
|
+
set("px", add(variable("px"), mul(variable("vx"), DELTA))),
|
|
859
|
+
set("py", add(variable("py"), mul(variable("vy"), DELTA))),
|
|
860
|
+
set("pz", add(variable("pz"), mul(variable("vz"), DELTA))),
|
|
861
|
+
when(lt(variable("py"), FLOOR), [
|
|
862
|
+
set("py", FLOOR),
|
|
863
|
+
set("vy", mul(variable("vy"), BOUNCE)),
|
|
864
|
+
set("vx", mul(variable("vx"), SIDE_LOSS)),
|
|
865
|
+
set("vz", mul(variable("vz"), SIDE_LOSS))
|
|
866
|
+
]),
|
|
867
|
+
cue("grenade_move", { position: [variable("px"), variable("py"), variable("pz")] })
|
|
868
|
+
], [
|
|
869
|
+
when(not(variable("boom")), [
|
|
870
|
+
set("boom", true),
|
|
871
|
+
cue("grenade_visible", { visible: false }),
|
|
872
|
+
call2("explode", [variable("px"), 0, variable("pz")], 1),
|
|
873
|
+
repeat(
|
|
874
|
+
BODIES.length,
|
|
875
|
+
cue("zombie_turn_and_fall", {
|
|
876
|
+
index: INDEX,
|
|
877
|
+
turn: atan2(neg(sub(pick(BODY_X, INDEX), variable("px"))), neg(sub(pick(BODY_Z2, INDEX), variable("pz")))),
|
|
878
|
+
delay: 0.02,
|
|
879
|
+
duration: 0.45
|
|
880
|
+
})
|
|
881
|
+
)
|
|
882
|
+
])
|
|
883
|
+
])
|
|
884
|
+
]
|
|
885
|
+
};
|
|
886
|
+
var BARREL = [-4.4, 0, 1.4];
|
|
887
|
+
var UP7 = [0, 1, 0];
|
|
888
|
+
var RED = 10165272;
|
|
889
|
+
var YELLOW = 14200874;
|
|
890
|
+
var POOLS = 3;
|
|
891
|
+
var above = (height) => vadd(BARREL, [0, height, 0]);
|
|
892
|
+
var EXPLOSIVE_BARREL = {
|
|
893
|
+
id: "explosive_barrel",
|
|
894
|
+
pageId: "barril",
|
|
895
|
+
team: "weapons",
|
|
896
|
+
lab: "barrel",
|
|
897
|
+
budget: { particles: 450, lights: 1 },
|
|
898
|
+
loop: 9,
|
|
899
|
+
view: { eye: [2.4, 3, 7.5], target: [-4.4, 1.6, 1.4] },
|
|
900
|
+
setup: [cue("zombie_visible", { index: -1, visible: false })],
|
|
901
|
+
timeline: [
|
|
902
|
+
set("pools", []),
|
|
903
|
+
after(
|
|
904
|
+
0.4,
|
|
905
|
+
cue("barrel_visible", { visible: false }),
|
|
906
|
+
call2("explode", BARREL, 1.3, RED),
|
|
907
|
+
burst("add", 30, { p: above(0.8), r: 0.4, dir: UP7, cone: 0.25, sp: [3, 5], drag: 1.2, life: [1, 1.6], size: [0.9, 1.4], grow: 1.4, c0: 16756816, c1: 3804421, g: -1, fi: 0.05 }),
|
|
908
|
+
debris({ p: above(1), v: [0.6, 9, 0.3], sp: 0, size: [0.7, 0.05, 0.7], c: RED, spin: 8, life: 12 }),
|
|
909
|
+
repeat(scaled(8), debris({ p: BARREL, dir: UP7, cone: 1, sp: [3, 7], size: [0.25, 0.04, 0.18], c: ite(mod(INDEX, 2), RED, YELLOW), life: 12 })),
|
|
910
|
+
repeat(
|
|
911
|
+
POOLS,
|
|
912
|
+
set("poolAngle", add(mul(INDEX, 2.1), rnd(0, 0.6))),
|
|
913
|
+
append("pools", vadd(BARREL, [mul(cos(variable("poolAngle")), 1.4), 0.05, mul(sin(variable("poolAngle")), 1.4)]))
|
|
914
|
+
)
|
|
915
|
+
)
|
|
916
|
+
],
|
|
917
|
+
tick: [
|
|
918
|
+
when(and(variable("pools"), gt(TIME, 0.5), lt(TIME, 6)), [
|
|
919
|
+
set("poolFade", ite(gt(TIME, 5), sub(1, sub(TIME, 5)), 1)),
|
|
920
|
+
repeat(POOLS, call2("fire_emit", concat("bp", INDEX), { $: "at", a: [variable("pools"), INDEX] }, 0.45, mul(0.6, variable("poolFade")), { smoke: 6 })),
|
|
921
|
+
fireLight(0, above(1), mul(2.6, variable("poolFade")), TIME)
|
|
922
|
+
]),
|
|
923
|
+
when(and(gt(TIME, 0.6), lt(TIME, 8)), [
|
|
924
|
+
emit("col", "normal", 6, { p: above(1.5), r: 0.6, dir: UP7, cone: 0.2, sp: [1.5, 2.5], v: [0.4, 0, 0], drag: 0.05, life: [4, 6], size: [1.2, 1.8], grow: 3, c0: 1710103, c1: 789776, a: 0.5, fi: 0.2 })
|
|
925
|
+
]),
|
|
926
|
+
when(ge(TIME, 6), [fireLightOff(0)])
|
|
927
|
+
]
|
|
928
|
+
};
|
|
929
|
+
var WEAPONS = ["glock", "ak", "r870", "barrett"];
|
|
930
|
+
var TIP2 = [-0.8, 1.38, 3.4 - 0.78];
|
|
931
|
+
var PORT2 = [-0.76, 1.4, 3.32];
|
|
932
|
+
var FORWARD3 = [0, 0, -1];
|
|
933
|
+
var NORMAL = [0, 0, 1];
|
|
934
|
+
var WALL_Z2 = -4.45;
|
|
935
|
+
var SHOTS = [[0, 0.45, 0.9], [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6], [0], [0]];
|
|
936
|
+
var SHOT_TIME = pick(pick(SHOTS, PARAM), INDEX);
|
|
937
|
+
var AK = 1;
|
|
938
|
+
var SHOTGUN = 2;
|
|
939
|
+
var BARRETT = 3;
|
|
940
|
+
var MUZZLE_FLASH = {
|
|
941
|
+
id: "muzzle_flash",
|
|
942
|
+
pageId: "muzzle",
|
|
943
|
+
team: "weapons",
|
|
944
|
+
params: { id: "weapon", options: ["glock", "ak", "r870", "barrett"], default: 1 },
|
|
945
|
+
budget: { particles: 60, lights: 1 },
|
|
946
|
+
loop: 2.4,
|
|
947
|
+
view: { eye: [1.8, 1.8, 5.2], target: [-0.8, 1.3, 1.4] },
|
|
948
|
+
timeline: [
|
|
949
|
+
repeat(
|
|
950
|
+
param(3, 7, 1, 1),
|
|
951
|
+
after(
|
|
952
|
+
add(0.2, SHOT_TIME),
|
|
953
|
+
call2("muzzle", pick(WEAPONS, PARAM), TIP2, FORWARD3),
|
|
954
|
+
when(ne(PARAM, SHOTGUN), [call2("casing", PORT2, ite(eq(PARAM, BARRETT), "50", ""))]),
|
|
955
|
+
set("target", [add(-0.8, rnd(-0.4, 0.4)), add(1.4, rnd(-0.3, 0.3)), WALL_Z2]),
|
|
956
|
+
when(
|
|
957
|
+
eq(PARAM, SHOTGUN),
|
|
958
|
+
[repeat(8, call2("impact", "concrete", [add(-0.8, rnd(-0.5, 0.5)), add(1.4, rnd(-0.4, 0.4)), WALL_Z2], NORMAL, 0.35))],
|
|
959
|
+
[call2("impact", "concrete", variable("target"), NORMAL, ite(eq(PARAM, BARRETT), 2, 1))]
|
|
960
|
+
),
|
|
961
|
+
when(and(eq(PARAM, AK), eq(mod(round(mul(SHOT_TIME, 10)), 3), 0)), [spawn("streak", { p: TIP2, dir: FORWARD3, cone: 0, sp: 90, life: 0.09, len: 0.025, c0: 16752704, a: 1 })])
|
|
962
|
+
)
|
|
963
|
+
),
|
|
964
|
+
when(eq(PARAM, SHOTGUN), [after(0.75, call2("casing", PORT2, "shell"))])
|
|
965
|
+
]
|
|
966
|
+
};
|
|
967
|
+
var FACING2 = [0, 0, 1];
|
|
968
|
+
var SHOPFRONT_GLASS = {
|
|
969
|
+
id: "shopfront_glass",
|
|
970
|
+
pageId: "vidro",
|
|
971
|
+
team: "destruction",
|
|
972
|
+
budget: { debris: 80, decals: 1 },
|
|
973
|
+
loop: 5,
|
|
974
|
+
view: { eye: [-2.4, 1.8, 1.2], target: [-5, 1.4, -4] },
|
|
975
|
+
timeline: [
|
|
976
|
+
after(0.3, call2("impact", "glass", [-5.4, 2.2, -4.45], FACING2), behavior("cracks", "crack", { x: 97, y: 59, big: false })),
|
|
977
|
+
after(1, call2("impact", "glass", [-4.5, 1.6, -4.45], FACING2), behavior("cracks", "crack", { x: 177, y: 108, big: true })),
|
|
978
|
+
after(
|
|
979
|
+
1.8,
|
|
980
|
+
cue("glass_pane_gone"),
|
|
981
|
+
screen({ add: { shake: 0.08 } }),
|
|
982
|
+
repeat(
|
|
983
|
+
scaled(75),
|
|
984
|
+
debris({ p: [-5, 1.9, -4.42], box: [1.25, 0.85, 0.02], v: [rnd(-0.4, 0.4), rnd(-0.5, 0.8), rnd(0.6, 2)], sp: 0, size: [rnd(0.05, 0.18), 6e-3, rnd(0.05, 0.18)], c: 11061464, spin: 14, life: 30, bounce: 0.15 })
|
|
985
|
+
),
|
|
986
|
+
burst("add", 30, { p: [-5, 1.9, -4.3], box: [1.2, 0.8, 0.05], size: [0.02, 0.05], life: [0.2, 0.6], c0: 16777215, a: 0.9, fi: 0.3 }),
|
|
987
|
+
burst("normal", 20, { p: [-5, 1.3, -4.2], box: [1.2, 0.5, 0.1], sp: [0.2, 0.6], drag: 2, life: [0.8, 1.4], size: [0.12, 0.2], grow: 3, c0: 12572386, a: 0.2 })
|
|
988
|
+
)
|
|
989
|
+
]
|
|
990
|
+
};
|
|
991
|
+
function normalized(vector) {
|
|
992
|
+
const length = Math.sqrt(vector[0] * vector[0] + vector[1] * vector[1] + vector[2] * vector[2]) || 1;
|
|
993
|
+
const inverse = 1 / length;
|
|
994
|
+
return [vector[0] * inverse, vector[1] * inverse, vector[2] * inverse];
|
|
995
|
+
}
|
|
996
|
+
var FRAME_DUST = normalized([0, -0.3, 1]);
|
|
997
|
+
var SPLINTER_DIRECTION = normalized([0, 0.3, 1]);
|
|
998
|
+
var FALL_SECONDS = 0.4;
|
|
999
|
+
var blow = (heavy) => [
|
|
1000
|
+
cue("door_shake", { strength: 0.25 }),
|
|
1001
|
+
burst("normal", heavy ? 24 : 12, { p: [2, 2.3, -4.38], box: [0.6, 0.05, 0.02], dir: FRAME_DUST, cone: 0.6, sp: [0.2, 0.8], drag: 1.5, life: [0.8, 1.4], size: [0.08, 0.16], grow: 3, c0: 8024934, a: 0.45, g: 0.4 }),
|
|
1002
|
+
repeat(scaled(heavy ? 5 : 2), debris({ p: [add(2, rnd(-0.5, 0.5)), rnd(0.4, 2), -4.36], dir: SPLINTER_DIRECTION, cone: 0.6, sp: [1, 2.5], size: [0.015, 0.015, 0.1], c: 8017200, life: 12 }))
|
|
1003
|
+
];
|
|
1004
|
+
var DOOR_STAGES = {
|
|
1005
|
+
id: "door_stages",
|
|
1006
|
+
pageId: "porta",
|
|
1007
|
+
team: "destruction",
|
|
1008
|
+
budget: { particles: 120, debris: 6 },
|
|
1009
|
+
loop: 7.5,
|
|
1010
|
+
view: { eye: [4.2, 1.7, 1.4], target: [2, 1.1, -4] },
|
|
1011
|
+
setup: [behavior("walkers", "place", { index: 0, x: 2, z: -5.4, facing: 0 })],
|
|
1012
|
+
timeline: [
|
|
1013
|
+
after(0.5, ...blow(false)),
|
|
1014
|
+
after(1.2, ...blow(false)),
|
|
1015
|
+
after(1.9, ...blow(true), cue("door_plank_crack", { stage: 1 })),
|
|
1016
|
+
after(2.7, ...blow(false)),
|
|
1017
|
+
after(
|
|
1018
|
+
3.3,
|
|
1019
|
+
...blow(true),
|
|
1020
|
+
cue("door_plank_fall", { stage: 2 }),
|
|
1021
|
+
repeat(3, debris({ p: [add(2, mul(sub(INDEX, 1), 0.4)), 1.1, -4.3], v: [rnd(-0.3, 0.3), 0.5, 1.2], sp: 0, size: [0.38, 0.68, 0.07], c: 5913634, spin: 4, life: 20, bounce: 0.15 }))
|
|
1022
|
+
),
|
|
1023
|
+
after(4.4, set("fall", 0), set("falling", true), cue("door_fall", { stage: 3 })),
|
|
1024
|
+
after(4.6, behavior("walkers", "walk", { index: 0, to: [2, 0, -2.2], speed: 0.9 }))
|
|
1025
|
+
],
|
|
1026
|
+
tick: [
|
|
1027
|
+
when(variable("falling"), [
|
|
1028
|
+
set("fall", add(variable("fall"), DELTA)),
|
|
1029
|
+
set("progress", min(1, div(variable("fall"), FALL_SECONDS))),
|
|
1030
|
+
when(and(ge(variable("progress"), 1), not(variable("landed"))), [
|
|
1031
|
+
set("landed", true),
|
|
1032
|
+
screen({ add: { shake: 0.2 } }),
|
|
1033
|
+
burst("normal", 45, { p: [2, 0.15, -3.4], box: [0.7, 0.05, 1], dir: [0, 1, 0], cone: 1.4, sp: [0.6, 2], drag: 1.8, life: [1.5, 2.8], size: [0.25, 0.5], grow: 3, c0: 6972506, a: 0.45 })
|
|
1034
|
+
])
|
|
1035
|
+
])
|
|
1036
|
+
]
|
|
1037
|
+
};
|
|
1038
|
+
var CENTRE2 = [-1.4, 3.35, -3.75];
|
|
1039
|
+
var BUILDING_COLLAPSE = {
|
|
1040
|
+
id: "building_collapse",
|
|
1041
|
+
pageId: "desaba",
|
|
1042
|
+
team: "destruction",
|
|
1043
|
+
budget: { particles: 350, debris: 26 },
|
|
1044
|
+
loop: 8,
|
|
1045
|
+
view: { eye: [4, 2.4, 5], target: [-1.4, 1.4, -2.8] },
|
|
1046
|
+
setup: [cue("zombie_visible", { index: -1, visible: false })],
|
|
1047
|
+
timeline: [
|
|
1048
|
+
after(
|
|
1049
|
+
1.5,
|
|
1050
|
+
cue("slab_gone"),
|
|
1051
|
+
screen({ add: { shake: 0.3 } }),
|
|
1052
|
+
repeat(6, debris({ p: CENTRE2, box: [2, 0.05, 0.6], v: [rnd(-0.5, 0.5), rnd(-0.5, 0), rnd(0, 0.8)], sp: 0, size: [rnd(0.5, 1.1), 0.25, rnd(0.4, 0.8)], c: 7236195, spin: 3, life: 30, bounce: 0.1 })),
|
|
1053
|
+
repeat(scaled(20), debris({ p: CENTRE2, box: [2.1, 0.1, 0.7], v: [rnd(-1, 1), rnd(-1, 1), rnd(0, 1.5)], sp: 0, size: [0.12, 0.1, 0.12], k: [0.5, 1.5], c: 6183508, life: 30 }))
|
|
1054
|
+
),
|
|
1055
|
+
after(
|
|
1056
|
+
2.15,
|
|
1057
|
+
screen({ add: { shake: 0.45 } }),
|
|
1058
|
+
repeat(
|
|
1059
|
+
scaled(70),
|
|
1060
|
+
spawn("normal", local("angle", rnd(-0.4, 3.5), {
|
|
1061
|
+
p: [add(-1.4, rnd(-2, 2)), 0.2, add(-3.4, rnd(-0.5, 0.5))],
|
|
1062
|
+
dir: vnorm([mul(cos(variable("angle")), 0.6), 0.25, abs(sin(variable("angle")))]),
|
|
1063
|
+
cone: 0.5,
|
|
1064
|
+
sp: [1, 3.2],
|
|
1065
|
+
drag: 1.1,
|
|
1066
|
+
life: [3, 6],
|
|
1067
|
+
size: [0.7, 1.2],
|
|
1068
|
+
grow: 3,
|
|
1069
|
+
c0: 8024680,
|
|
1070
|
+
c1: 4867648,
|
|
1071
|
+
a: 0.5,
|
|
1072
|
+
fi: 0.12
|
|
1073
|
+
}))
|
|
1074
|
+
)
|
|
1075
|
+
)
|
|
1076
|
+
],
|
|
1077
|
+
tick: [
|
|
1078
|
+
when(and(gt(TIME, 0.3), lt(TIME, 1.5)), [
|
|
1079
|
+
emit("trk", "normal", 30, { p: [add(-1.4, rnd(-2, 2)), 3.2, -3.05], dir: [0, -1, 0], cone: 0.1, sp: [0.2, 0.5], life: [1, 1.6], size: [0.04, 0.08], grow: 2.5, c0: 9077880, a: 0.5, g: 1 }),
|
|
1080
|
+
when(lt(rand(), mul(DELTA, 6)), [debris({ p: [add(-1.4, rnd(-2, 2)), 3.2, -3.05], sp: 0.2, size: [0.04, 0.04, 0.04], c: 7236195, life: 10 })])
|
|
1081
|
+
])
|
|
1082
|
+
]
|
|
1083
|
+
};
|
|
1084
|
+
var FIRING_FROM = [0.6, 1.3, 7];
|
|
1085
|
+
var FIRING_DIRECTION = normalized([-2.8, -0.4, -4.4]);
|
|
1086
|
+
var WALL_CENTRE = [-2.2, 1, 2.6];
|
|
1087
|
+
var BLOCK_WALL = {
|
|
1088
|
+
id: "block_wall",
|
|
1089
|
+
pageId: "parede",
|
|
1090
|
+
team: "destruction",
|
|
1091
|
+
budget: { particles: 300, debris: 16 },
|
|
1092
|
+
loop: 8,
|
|
1093
|
+
view: { eye: [0.4, 1.7, 6.6], target: [-2.2, 0.9, 2.4] },
|
|
1094
|
+
props: ["blocks"],
|
|
1095
|
+
setup: [cue("zombie_visible", { index: -1, visible: false }), cue("work_light", { intensity: 2.2 })],
|
|
1096
|
+
timeline: [
|
|
1097
|
+
repeat(
|
|
1098
|
+
14,
|
|
1099
|
+
after(
|
|
1100
|
+
add(0.3, mul(INDEX, 0.11)),
|
|
1101
|
+
call2("muzzle", "ak", FIRING_FROM, FIRING_DIRECTION),
|
|
1102
|
+
behavior("blocks", "hit", { x: rnd(-1.3, 1.3), y: rnd(0.4, 1.9), scale: 1 })
|
|
1103
|
+
)
|
|
1104
|
+
),
|
|
1105
|
+
after(2.2, behavior("blocks", "hit", { x: -0.2, y: 1.1, scale: 2.2 })),
|
|
1106
|
+
after(
|
|
1107
|
+
3,
|
|
1108
|
+
screen({ add: { shake: 0.4 } }),
|
|
1109
|
+
behavior("blocks", "collapse", { x: -0.2, y: 1.1 }),
|
|
1110
|
+
burst("normal", 30, { p: WALL_CENTRE, box: [1.4, 0.8, 0.2], sp: [0.3, 1.2], drag: 1.5, life: [1.5, 2.6], size: [0.4, 0.7], grow: 3, c0: 9078138, c1: 4867648, a: 0.45 }),
|
|
1111
|
+
repeat(scaled(16), debris({ p: WALL_CENTRE, box: [1.3, 0.8, 0.1], sp: [1, 3], size: [0.08, 0.07, 0.08], k: [0.5, 1.5], c: 7236195, life: 20 }))
|
|
1112
|
+
),
|
|
1113
|
+
after(
|
|
1114
|
+
3.6,
|
|
1115
|
+
screen({ add: { shake: 0.25 } }),
|
|
1116
|
+
repeat(
|
|
1117
|
+
scaled(60),
|
|
1118
|
+
spawn("normal", local("angle", rnd(0, 6.283), {
|
|
1119
|
+
p: [add(-2.2, rnd(-1.4, 1.4)), 0.2, add(2.4, rnd(-0.6, 0.4))],
|
|
1120
|
+
dir: vnorm([cos(variable("angle")), 0.3, sin(variable("angle"))]),
|
|
1121
|
+
cone: 0.4,
|
|
1122
|
+
sp: [0.8, 2.4],
|
|
1123
|
+
drag: 1.3,
|
|
1124
|
+
life: [2.5, 4.5],
|
|
1125
|
+
size: [0.6, 1],
|
|
1126
|
+
grow: 3,
|
|
1127
|
+
c0: 8024680,
|
|
1128
|
+
c1: 4867648,
|
|
1129
|
+
a: 0.45,
|
|
1130
|
+
fi: 0.12
|
|
1131
|
+
}))
|
|
1132
|
+
)
|
|
1133
|
+
)
|
|
1134
|
+
]
|
|
1135
|
+
};
|
|
1136
|
+
var SPOT = [-2.2, 0, 2.6];
|
|
1137
|
+
var UP8 = [0, 1, 0];
|
|
1138
|
+
var HITS = [[0.4, 1.4], [0.75, 1], [0.3, 0.7], [0.6, 1.7], [0.5, 1.2]];
|
|
1139
|
+
var HIT_X = HITS.map(([x]) => x);
|
|
1140
|
+
var HIT_Y = HITS.map(([, y]) => y);
|
|
1141
|
+
var SPARK_DIRECTION = normalized([0, 0.3, 1]);
|
|
1142
|
+
var CHIP_DIRECTION = normalized([0, 0.2, 1]);
|
|
1143
|
+
var HINGE_DIRECTION = normalized([1, 0.3, 1]);
|
|
1144
|
+
var SCRAPE_DIRECTION = normalized([0, 0.4, 1]);
|
|
1145
|
+
var FALL_SECONDS2 = 0.45;
|
|
1146
|
+
var SCRAPES = 5;
|
|
1147
|
+
var METAL_DOOR_EFFECT = {
|
|
1148
|
+
id: "metal_door",
|
|
1149
|
+
pageId: "portametal",
|
|
1150
|
+
team: "destruction",
|
|
1151
|
+
budget: { particles: 160, debris: 20 },
|
|
1152
|
+
loop: 7.5,
|
|
1153
|
+
view: { eye: [0.6, 1.6, 6.2], target: [-2.2, 1.1, 2.6] },
|
|
1154
|
+
props: ["plate"],
|
|
1155
|
+
setup: [
|
|
1156
|
+
cue("zombie_visible", { index: -1, visible: false }),
|
|
1157
|
+
cue("work_light", { intensity: 2.2 }),
|
|
1158
|
+
behavior("walkers", "place", { index: 3, x: SPOT[0] + 0.1, z: SPOT[2] - 0.7, facing: 0 })
|
|
1159
|
+
],
|
|
1160
|
+
timeline: [
|
|
1161
|
+
repeat(
|
|
1162
|
+
HITS.length,
|
|
1163
|
+
after(
|
|
1164
|
+
add(0.5, mul(INDEX, 0.75)),
|
|
1165
|
+
cue("zombie_swing", { index: 3, side: mod(INDEX, 2) }),
|
|
1166
|
+
after(
|
|
1167
|
+
add(0.5, mul(INDEX, 0.75), 0.15),
|
|
1168
|
+
behavior("plate", "dent", { x: pick(HIT_X, INDEX), y: pick(HIT_Y, INDEX), radius: 0.42, depth: add(0.09, mul(INDEX, 0.025)) }),
|
|
1169
|
+
set("spot", [add(SPOT[0] - 0.56, pick(HIT_X, INDEX)), pick(HIT_Y, INDEX), SPOT[2] + 0.06]),
|
|
1170
|
+
call2("spark_at", variable("spot"), SPARK_DIRECTION, 8),
|
|
1171
|
+
repeat(scaled(5), debris({ p: variable("spot"), dir: CHIP_DIRECTION, cone: 0.9, sp: [0.8, 2.2], size: [0.035, 4e-3, 0.03], k: [0.6, 1.4], c: ite(mod(INDEX, 2), 5333594, 9080710), life: 20, spin: 16 })),
|
|
1172
|
+
call2("rust_at", variable("spot"), 6),
|
|
1173
|
+
cue("door_dent", { level: min(3, add(1, floor(div(INDEX, 1.7)))) })
|
|
1174
|
+
)
|
|
1175
|
+
)
|
|
1176
|
+
),
|
|
1177
|
+
after(4.4, call2("spark_at", [SPOT[0] - 0.6, 2.05, SPOT[2] + 0.05], HINGE_DIRECTION, 30, 1.2), screen({ add: { shake: 0.15 } }), set("fall", 0), set("falling", true), cue("door_hinge_burst")),
|
|
1178
|
+
after(5.2, behavior("walkers", "walk", { index: 3, to: [SPOT[0], 0, SPOT[2] + 2.4], speed: 0.8 }))
|
|
1179
|
+
],
|
|
1180
|
+
tick: [
|
|
1181
|
+
when(variable("falling"), [
|
|
1182
|
+
set("fall", add(variable("fall"), DELTA)),
|
|
1183
|
+
set("progress", min(1, div(variable("fall"), FALL_SECONDS2))),
|
|
1184
|
+
when(and(ge(variable("progress"), 1), not(variable("landed"))), [
|
|
1185
|
+
set("landed", true),
|
|
1186
|
+
screen({ add: { shake: 0.3 } }),
|
|
1187
|
+
repeat(SCRAPES, call2("spark_at", [add(SPOT[0] - 0.5, mul(INDEX, 0.27)), 0.03, SPOT[2] + 2.1], SCRAPE_DIRECTION, 8, 1)),
|
|
1188
|
+
burst("normal", 40, { p: [SPOT[0], 0.15, SPOT[2] + 1.2], box: [0.6, 0.05, 1], dir: UP8, cone: 1.4, sp: [0.6, 2], drag: 1.8, life: [1.4, 2.4], size: [0.25, 0.5], grow: 3, c0: 6972506, a: 0.45 })
|
|
1189
|
+
])
|
|
1190
|
+
])
|
|
1191
|
+
]
|
|
1192
|
+
};
|
|
1193
|
+
var PUSHERS = [[-0.6, 0.45], [0.1, 0.5], [0.6, 0.42], [-0.1, 1]];
|
|
1194
|
+
var BEND_LIMIT = 0.42;
|
|
1195
|
+
var BEND_STEP = 4e-3;
|
|
1196
|
+
var FALL_SECONDS3 = 0.55;
|
|
1197
|
+
var WELD = normalized([0, 0.3, 1]);
|
|
1198
|
+
var IRON_RAILING = {
|
|
1199
|
+
id: "iron_railing",
|
|
1200
|
+
pageId: "grade",
|
|
1201
|
+
team: "destruction",
|
|
1202
|
+
budget: { particles: 200 },
|
|
1203
|
+
loop: 7.5,
|
|
1204
|
+
view: { eye: [1.4, 1.8, 6.4], target: [-2.2, 0.7, 2.4] },
|
|
1205
|
+
setup: [
|
|
1206
|
+
cue("zombie_visible", { index: -1, visible: false }),
|
|
1207
|
+
cue("work_light", { intensity: 2.2 }),
|
|
1208
|
+
set("bend", 0),
|
|
1209
|
+
...PUSHERS.map(([x, dz], index) => behavior("walkers", "place", { index, x: SPOT[0] + x, z: SPOT[2] - dz, facing: 0 }))
|
|
1210
|
+
],
|
|
1211
|
+
timeline: [
|
|
1212
|
+
after(1.6, call2("spark_at", [SPOT[0], 0.75, SPOT[2] + 0.05], WELD, 20, 1), screen({ add: { shake: 0.08 } }), cue("weld_burst")),
|
|
1213
|
+
after(3.2, call2("spark_at", [SPOT[0] + 0.02, 1.2, SPOT[2] + 0.1], WELD, 20, 1), screen({ add: { shake: 0.1 } })),
|
|
1214
|
+
after(
|
|
1215
|
+
4.3,
|
|
1216
|
+
set("fall", 0),
|
|
1217
|
+
set("falling", true),
|
|
1218
|
+
call2("spark_at", [SPOT[0] - 1.5, 0.25, SPOT[2]], normalized([-0.3, 0.5, 1]), 14, 1),
|
|
1219
|
+
call2("spark_at", [SPOT[0] + 1.5, 0.25, SPOT[2]], normalized([0.3, 0.5, 1]), 14, 1),
|
|
1220
|
+
cue("railing_gave_way")
|
|
1221
|
+
),
|
|
1222
|
+
after(
|
|
1223
|
+
4.9,
|
|
1224
|
+
repeat(PUSHERS.length, behavior("walkers", "walk", { index: INDEX, to: [add(SPOT[0], pick(PUSHERS.map(([x]) => x), INDEX)), 0, add(SPOT[2], 2.6, mul(INDEX, 0.3))], speed: 0.7 }))
|
|
1225
|
+
)
|
|
1226
|
+
],
|
|
1227
|
+
tick: [
|
|
1228
|
+
when(lt(TIME, 4.3), [
|
|
1229
|
+
set("target", min(BEND_LIMIT, mul(TIME, 0.1))),
|
|
1230
|
+
when(gt(sub(variable("target"), variable("bend")), BEND_STEP), [set("bend", variable("target")), cue("railing_bend", { amount: variable("bend") })]),
|
|
1231
|
+
emit("rust", "normal", 10, { p: [add(SPOT[0], rnd(-0.6, 0.6)), rnd(0.3, 1.2), add(SPOT[2], mul(variable("bend"), 0.8))], sp: [0, 0.2], life: [0.8, 1.2], size: [0.015, 0.03], c0: 8014378, a: 0.9, g: 6, fi: 0, gnd: 1 })
|
|
1232
|
+
]),
|
|
1233
|
+
when(variable("falling"), [
|
|
1234
|
+
set("fall", add(variable("fall"), DELTA)),
|
|
1235
|
+
set("progress", min(1, div(variable("fall"), FALL_SECONDS3))),
|
|
1236
|
+
when(and(ge(variable("progress"), 1), not(variable("landed"))), [
|
|
1237
|
+
set("landed", true),
|
|
1238
|
+
screen({ add: { shake: 0.25 } }),
|
|
1239
|
+
repeat(4, call2("spark_at", [add(SPOT[0] - 1.2, mul(INDEX, 0.8)), 0.04, SPOT[2] + 1.2], normalized([0, 0.5, 1]), 6, 1)),
|
|
1240
|
+
burst("normal", 30, { p: [SPOT[0], 0.12, SPOT[2] + 0.8], box: [1.4, 0.05, 0.5], dir: UP8, cone: 1.4, sp: [0.5, 1.6], drag: 1.8, life: [1.2, 2.2], size: [0.2, 0.4], grow: 3, c0: 6972506, a: 0.4 })
|
|
1241
|
+
])
|
|
1242
|
+
])
|
|
1243
|
+
]
|
|
1244
|
+
};
|
|
1245
|
+
var ORDER = [3, 4, 8, 5, 9, 2, 7];
|
|
1246
|
+
var PLANK_X = Array.from({ length: 12 }, (_, index) => -1.43 + index * 0.26);
|
|
1247
|
+
var BODIES2 = [[-0.8, 0.6], [0.5, 0.7], [0, 1.2]];
|
|
1248
|
+
var SPLINTER_DIRECTION2 = normalized([0, 0.4, 1]);
|
|
1249
|
+
var FALL_SECONDS4 = 0.5;
|
|
1250
|
+
var PLANK_HEIGHT = 1.3;
|
|
1251
|
+
var WOODEN_FENCE = {
|
|
1252
|
+
id: "wooden_fence",
|
|
1253
|
+
pageId: "cerca",
|
|
1254
|
+
team: "destruction",
|
|
1255
|
+
budget: { particles: 150, debris: 12 },
|
|
1256
|
+
loop: 7.5,
|
|
1257
|
+
view: { eye: [1, 1.6, 6], target: [-2.2, 0.7, 2.4] },
|
|
1258
|
+
setup: [
|
|
1259
|
+
cue("zombie_visible", { index: -1, visible: false }),
|
|
1260
|
+
cue("work_light", { intensity: 2.2 }),
|
|
1261
|
+
...BODIES2.map(([x, dz], index) => behavior("walkers", "place", { index, x: SPOT[0] + x, z: SPOT[2] - dz, facing: 0 }))
|
|
1262
|
+
],
|
|
1263
|
+
timeline: [
|
|
1264
|
+
repeat(
|
|
1265
|
+
ORDER.length,
|
|
1266
|
+
after(
|
|
1267
|
+
add(0.4, mul(INDEX, 0.5)),
|
|
1268
|
+
set("cut", rnd(0.32, 0.6)),
|
|
1269
|
+
set("top", sub(PLANK_HEIGHT, variable("cut"))),
|
|
1270
|
+
set("break", [add(SPOT[0], pick(PLANK_X, pick(ORDER, INDEX))), variable("cut"), SPOT[2]]),
|
|
1271
|
+
cue("zombie_swing", { index: mod(INDEX, 3), side: mod(INDEX, 2) }),
|
|
1272
|
+
cue("plank_snap", { plank: pick(ORDER, INDEX), cut: variable("cut") }),
|
|
1273
|
+
debris({ p: vadd(variable("break"), [0, div(variable("top"), 2), 0]), v: [rnd(-0.8, 0.8), rnd(1.5, 3), rnd(1.5, 3)], sp: 0, size: [0.17, variable("top"), 0.035], c: 9071172, spin: 7, life: 20, bounce: 0.2 }),
|
|
1274
|
+
repeat(scaled(6), debris({ p: variable("break"), dir: SPLINTER_DIRECTION2, cone: 0.9, sp: [1, 3], size: [0.012, 0.012, 0.1], k: [0.6, 1.4], c: 11569754, life: 20 })),
|
|
1275
|
+
burst("normal", 8, { p: variable("break"), dir: [0, 0, 1], cone: 0.8, sp: [0.4, 1.4], drag: 2, life: [0.8, 1.4], size: [0.1, 0.18], grow: 3, c0: 8020040, a: 0.4 })
|
|
1276
|
+
)
|
|
1277
|
+
),
|
|
1278
|
+
after(
|
|
1279
|
+
4.2,
|
|
1280
|
+
set("fall", 0),
|
|
1281
|
+
set("falling", true),
|
|
1282
|
+
repeat(scaled(10), debris({ p: [add(SPOT[0], rnd(-1.4, 1.4)), 1, SPOT[2]], dir: SPLINTER_DIRECTION2, cone: 0.9, sp: [1, 3], size: [0.012, 0.012, 0.1], c: 11569754, life: 20 })),
|
|
1283
|
+
cue("fence_rail_cracked")
|
|
1284
|
+
),
|
|
1285
|
+
after(4.8, repeat(BODIES2.length, behavior("walkers", "walk", { index: INDEX, to: [add(SPOT[0], pick(BODIES2.map(([x]) => x), INDEX)), 0, SPOT[2] + 2.5], speed: 0.75 })))
|
|
1286
|
+
],
|
|
1287
|
+
tick: [
|
|
1288
|
+
when(variable("falling"), [
|
|
1289
|
+
set("fall", add(variable("fall"), DELTA)),
|
|
1290
|
+
set("progress", min(1, div(variable("fall"), FALL_SECONDS4))),
|
|
1291
|
+
when(and(ge(variable("progress"), 1), not(variable("landed"))), [
|
|
1292
|
+
set("landed", true),
|
|
1293
|
+
screen({ add: { shake: 0.2 } }),
|
|
1294
|
+
burst("normal", 35, { p: [SPOT[0], 0.12, SPOT[2] + 0.8], box: [1.5, 0.05, 0.5], dir: UP8, cone: 1.4, sp: [0.5, 1.6], drag: 1.8, life: [1.2, 2.2], size: [0.25, 0.45], grow: 3, c0: 6969928, a: 0.4 })
|
|
1295
|
+
])
|
|
1296
|
+
])
|
|
1297
|
+
]
|
|
1298
|
+
};
|
|
1299
|
+
var at2 = (x, y, z) => [SPOT[0] + x, SPOT[1] + y, SPOT[2] + z];
|
|
1300
|
+
var FRONT_LEG = at2(-0.52, 0.2, 0.32);
|
|
1301
|
+
var TOP_CORNER = at2(0.3, 0.78, 0.2);
|
|
1302
|
+
var TOP_PIECE = at2(-0.3, 0.78, -0.2);
|
|
1303
|
+
var FAR_CORNER = at2(0.3, 0.78, -0.2);
|
|
1304
|
+
var HOLE_OBJECT_ID_DRAWS = 12;
|
|
1305
|
+
var HOLES = 9;
|
|
1306
|
+
var GLOCK_FROM = [-0.4, 1, 6];
|
|
1307
|
+
var SHOTGUN_FROM = [0.2, 1.1, 4.6];
|
|
1308
|
+
var toward = (target, from) => normalized([target[0] - from[0], target[1] - from[1], target[2] - from[2]]);
|
|
1309
|
+
var HIT_POINT_BREAKAGE = {
|
|
1310
|
+
id: "hit_point_breakage",
|
|
1311
|
+
pageId: "pontos",
|
|
1312
|
+
team: "destruction",
|
|
1313
|
+
budget: { particles: 120, debris: 20 },
|
|
1314
|
+
loop: 7.5,
|
|
1315
|
+
view: { eye: [0.2, 1.6, 5.4], target: [-2.2, 0.6, 2.6] },
|
|
1316
|
+
setup: [cue("zombie_visible", { index: -1, visible: false }), cue("work_light", { intensity: 2.2 })],
|
|
1317
|
+
timeline: [
|
|
1318
|
+
after(
|
|
1319
|
+
0.6,
|
|
1320
|
+
call2("muzzle", "glock", GLOCK_FROM, toward(FRONT_LEG, GLOCK_FROM)),
|
|
1321
|
+
call2("chips", FRONT_LEG, normalized([0, 0.2, 1]), 6),
|
|
1322
|
+
cue("table_part_detached", { part: "front_leg" }),
|
|
1323
|
+
debris({ p: FRONT_LEG, v: [0.4, 0.6, 1.4], sp: 0, size: [0.07, 0.4, 0.07], c: 8017200, spin: 6, life: 20, bounce: 0.25 }),
|
|
1324
|
+
cue("table_tilt")
|
|
1325
|
+
),
|
|
1326
|
+
after(
|
|
1327
|
+
2.2,
|
|
1328
|
+
repeat(8, call2("chips", vadd(TOP_CORNER, [add(-0.3, mul(INDEX, 0.08)), 0.03, 0]), normalized([0, 0.6, 1]), 1, 0.4)),
|
|
1329
|
+
cue("table_part_detached", { part: "top_corner" }),
|
|
1330
|
+
debris({ p: TOP_CORNER, v: [1.2, 1.5, 1], sp: 0, size: [0.6, 0.06, 0.4], c: 8017200, spin: 6, life: 20, bounce: 0.25 })
|
|
1331
|
+
),
|
|
1332
|
+
after(
|
|
1333
|
+
3.8,
|
|
1334
|
+
screen({ add: { shake: 0.12 } }),
|
|
1335
|
+
call2("chips", TOP_PIECE, UP8, 10, 1.3),
|
|
1336
|
+
cue("table_part_gone", { part: "top_piece" }),
|
|
1337
|
+
repeat(4, debris({ p: [add(TOP_PIECE[0], rnd(-0.2, 0.2)), TOP_PIECE[1], add(TOP_PIECE[2], rnd(-0.1, 0.1))], dir: UP8, cone: 1.2, sp: [1, 2.5], size: [rnd(0.15, 0.3), 0.06, rnd(0.12, 0.25)], c: 7031338, spin: 8, life: 20, bounce: 0.2 })),
|
|
1338
|
+
burst("normal", 20, { p: TOP_PIECE, r: 0.2, sp: [0.3, 1], drag: 2, life: [1, 1.8], size: [0.2, 0.35], grow: 3, c0: 8020040, a: 0.4 })
|
|
1339
|
+
),
|
|
1340
|
+
after(
|
|
1341
|
+
5.3,
|
|
1342
|
+
call2("muzzle", "r870", SHOTGUN_FROM, toward(FAR_CORNER, SHOTGUN_FROM)),
|
|
1343
|
+
repeat(HOLES, set("holeX", rnd(-0.15, 0.15)), set("holeZ", rnd(-0.1, 0.1)), cue("table_hole", { x: variable("holeX"), z: variable("holeZ") }, HOLE_OBJECT_ID_DRAWS)),
|
|
1344
|
+
call2("chips", FAR_CORNER, UP8, 10, 1)
|
|
1345
|
+
)
|
|
1346
|
+
]
|
|
1347
|
+
};
|
|
1348
|
+
var OXYGEN = 1;
|
|
1349
|
+
var PUNCTURE_AT = 0.6;
|
|
1350
|
+
var JET_SECONDS = 3.4;
|
|
1351
|
+
var CLOUD_UNTIL = 7;
|
|
1352
|
+
var SHOT_FROM = [0.4, 1.2, 6.4];
|
|
1353
|
+
var SHOT_DIRECTION = normalized([-0.5, -0.15, -1]);
|
|
1354
|
+
var SCRAPE_DIRECTION2 = normalized([1, 0.4, 0]);
|
|
1355
|
+
var jetStrength = variable("jet");
|
|
1356
|
+
var isOxygen = eq(PARAM, OXYGEN);
|
|
1357
|
+
var PRESSURE_CYLINDERS = {
|
|
1358
|
+
id: "pressure_cylinders",
|
|
1359
|
+
pageId: "pressao",
|
|
1360
|
+
team: "destruction",
|
|
1361
|
+
params: { id: "cylinder", options: ["extinguisher", "oxygen"], default: 0 },
|
|
1362
|
+
budget: { particles: 250 },
|
|
1363
|
+
loop: 7,
|
|
1364
|
+
view: { eye: [1.6, 1.5, 6.4], target: [-1.6, 0.4, 2.4] },
|
|
1365
|
+
props: ["cylinder"],
|
|
1366
|
+
setup: [cue("zombie_visible", { index: -1, visible: false }), cue("work_light", { intensity: 2.2 }), behavior("cylinder", "choose", { oxygen: isOxygen }), cue("cylinder_visible", { oxygen: isOxygen })],
|
|
1367
|
+
timeline: [
|
|
1368
|
+
after(
|
|
1369
|
+
PUNCTURE_AT,
|
|
1370
|
+
call2("muzzle", "glock", SHOT_FROM, SHOT_DIRECTION),
|
|
1371
|
+
screen({ add: { shake: 0.1 } }),
|
|
1372
|
+
behavior("cylinder", "puncture"),
|
|
1373
|
+
when(isOxygen, [call2("spark_at", [SPOT[0], 1.3, SPOT[2]], UP8, 20, 1.2)])
|
|
1374
|
+
)
|
|
1375
|
+
],
|
|
1376
|
+
tick: [
|
|
1377
|
+
when(query("cylinder", "live"), [
|
|
1378
|
+
set("jet", clamp(sub(1, div(sub(TIME, PUNCTURE_AT), JET_SECONDS)), 0, 1)),
|
|
1379
|
+
behavior("cylinder", "step", { dt: DELTA, t: TIME }),
|
|
1380
|
+
when(not(isOxygen), [
|
|
1381
|
+
when(gt(jetStrength, 0), [
|
|
1382
|
+
emit("jet", "normal", 60, { p: query("cylinder", "tip"), dir: query("cylinder", "direction"), cone: 0.3, sp: [3, 6], drag: 2.5, life: [2, 3.5], size: [0.15, 0.3], grow: 6, c0: 15658730, c1: 12567496, a: 0.45, g: -0.05, fi: 0.05 })
|
|
1383
|
+
]),
|
|
1384
|
+
when(lt(TIME, CLOUD_UNTIL), [
|
|
1385
|
+
emit("cloud", "normal", 4, { p: [SPOT[0], 0.6, SPOT[2]], r: 2.5, flat: true, sp: [0.05, 0.2], life: [3, 5], size: [1.5, 2.5], grow: 1.3, c0: 14869214, a: mul(0.18, min(1, sub(TIME, PUNCTURE_AT))), fi: 0.3 })
|
|
1386
|
+
])
|
|
1387
|
+
], [
|
|
1388
|
+
when(gt(jetStrength, 0), [
|
|
1389
|
+
emit("jet", "normal", 50, { p: query("cylinder", "back"), dir: [1, 0, 0], cone: 0.25, sp: [2, 4], drag: 3, life: [0.5, 0.9], size: [0.1, 0.2], grow: 4, c0: 14542574, a: 0.2 })
|
|
1390
|
+
]),
|
|
1391
|
+
when(gt(abs(query("cylinder", "speed_x")), 0.5), [
|
|
1392
|
+
emit("scr", "streak", 120, { p: [vx(query("cylinder", "position")), 0.03, vz(query("cylinder", "position"))], dir: SCRAPE_DIRECTION2, cone: 0.6, sp: [2, 6], v: [mul(query("cylinder", "speed_x"), 0.5), 0, 0], life: [0.2, 0.45], len: 0.02, c0: 16773312, c1: 16732176, g: 9.8, gnd: 2 })
|
|
1393
|
+
])
|
|
1394
|
+
])
|
|
1395
|
+
])
|
|
1396
|
+
]
|
|
1397
|
+
};
|
|
1398
|
+
var WINDOWS = [[4.6, 5, -4.48], [-1.6, 5, -4.48]];
|
|
1399
|
+
var BUILDING_FIRE = {
|
|
1400
|
+
id: "building_fire",
|
|
1401
|
+
pageId: "incendio",
|
|
1402
|
+
team: "world",
|
|
1403
|
+
budget: { particles: 600, lights: 2 },
|
|
1404
|
+
loop: 0,
|
|
1405
|
+
view: { eye: [3, 2.4, 6.5], target: [1.5, 4, -4] },
|
|
1406
|
+
setup: [cue("zombie_visible", { index: -1, visible: false })],
|
|
1407
|
+
timeline: [],
|
|
1408
|
+
tick: [
|
|
1409
|
+
repeat(
|
|
1410
|
+
WINDOWS.length,
|
|
1411
|
+
call2("fire_emit", concat("w", INDEX), vadd(pick(WINDOWS, INDEX), [0, 0.55, 0.12]), 0.55, 1.1, { dir: normalized([0, 1, 0.35]), wind: [0.9, 0, 0], smoke: 22, smokeAlpha: 0.5 }),
|
|
1412
|
+
when(eq(INDEX, 0), [fireLight(0, vadd(pick(WINDOWS, INDEX), [0, 0, 1.4]), 3, add(TIME, INDEX))], [fireLight(1, vadd(pick(WINDOWS, INDEX), [0, 0, 1.4]), 3, add(TIME, INDEX))])
|
|
1413
|
+
)
|
|
1414
|
+
]
|
|
1415
|
+
};
|
|
1416
|
+
var SPOTS_X = [-3, 1, 5];
|
|
1417
|
+
var SPOTS_Z = [-1, -2.4, 0.4];
|
|
1418
|
+
var FOG_AND_ASH = {
|
|
1419
|
+
id: "fog_and_ash",
|
|
1420
|
+
pageId: "neblina",
|
|
1421
|
+
team: "world",
|
|
1422
|
+
budget: { particles: 120, lights: 1 },
|
|
1423
|
+
loop: 0,
|
|
1424
|
+
view: { eye: [3, 1.8, 7.5], target: [-3, 1.2, -1] },
|
|
1425
|
+
setup: [
|
|
1426
|
+
cue("fog", { density: 0.075 }),
|
|
1427
|
+
cue("lamp_cone", { visible: true }),
|
|
1428
|
+
cue("zombie_visible", { index: -1, visible: false }),
|
|
1429
|
+
repeat(
|
|
1430
|
+
SPOTS_X.length,
|
|
1431
|
+
set("turn", rnd(-0.6, 0.6)),
|
|
1432
|
+
behavior("walkers", "place", { index: INDEX, x: pick(SPOTS_X, INDEX), z: pick(SPOTS_Z, INDEX), facing: variable("turn") })
|
|
1433
|
+
)
|
|
1434
|
+
],
|
|
1435
|
+
timeline: [],
|
|
1436
|
+
tick: [
|
|
1437
|
+
emit("fog", "normal", 5, { p: [rnd(-14, 10), rnd(0.2, 1.1), rnd(-3, 8)], v: [rnd(0.15, 0.35), 0, rnd(-0.05, 0.05)], sp: 0, life: [9, 13], size: [3, 5], grow: 1.4, c0: 8227488, a: 0.13, fi: 0.35 }),
|
|
1438
|
+
emit("ash", "normal", 14, { p: [rnd(-10, 8), rnd(4, 6), rnd(-3, 7)], v: [rnd(0.1, 0.4), -0.35, rnd(-0.1, 0.1)], sp: [0.05, 0.15], life: [8, 12], size: [0.025, 0.04], c0: 10525328, a: 0.75, fi: 0.1, gnd: 1 })
|
|
1439
|
+
]
|
|
1440
|
+
};
|
|
1441
|
+
var WORKSHOP_PUDDLES = [
|
|
1442
|
+
[-1.5, 2.2, 1.6, 0.9],
|
|
1443
|
+
[3, 3.6, 1.1, 0.7],
|
|
1444
|
+
[-6, 3.2, 1.3, 0.8],
|
|
1445
|
+
[1.4, -2.2, 0.9, 0.5]
|
|
1446
|
+
];
|
|
1447
|
+
var inPuddle = (puddles, x, z) => puddles.some((p) => ((x - p[0]) / p[2]) ** 2 + ((z - p[1]) / p[3]) ** 2 < 1);
|
|
1448
|
+
var DROPS = [900, 2200, 4e3];
|
|
1449
|
+
var SLANT = [0.3, 1.2, 4.5];
|
|
1450
|
+
var STORM = 2;
|
|
1451
|
+
var FLASH_STEPS = ite(lt(variable("flash"), 0.08), 1, ite(lt(variable("flash"), 0.16), 0.2, ite(lt(variable("flash"), 0.26), 0.8, 0)));
|
|
1452
|
+
var RAIN_AND_PUDDLES = {
|
|
1453
|
+
id: "rain_and_puddles",
|
|
1454
|
+
pageId: "chuva",
|
|
1455
|
+
team: "world",
|
|
1456
|
+
params: { id: "intensity", options: ["drizzle", "rain", "storm"], default: 1 },
|
|
1457
|
+
budget: { particles: 4e3, decals: 4 },
|
|
1458
|
+
loop: 0,
|
|
1459
|
+
view: { eye: [2, 2, 7], target: [-1, 0.6, 1] },
|
|
1460
|
+
setup: [
|
|
1461
|
+
cue("lamp_cone", { visible: true }),
|
|
1462
|
+
...WORKSHOP_PUDDLES.map(([x, z, radiusX, radiusZ]) => decal(x, 0, z, radiusX * 2, 790550, { grow: 0, life: 1e6, ar: radiusZ / radiusX }))
|
|
1463
|
+
],
|
|
1464
|
+
timeline: [
|
|
1465
|
+
behavior("rain", "init", { count: ite(eq(PARAM, 0), DROPS[0], ite(eq(PARAM, 1), DROPS[1], DROPS[2])), wind: ite(eq(PARAM, 0), SLANT[0], ite(eq(PARAM, 1), SLANT[1], SLANT[2])) }),
|
|
1466
|
+
set("nextStrike", rnd(2, 4)),
|
|
1467
|
+
set("flash", -1)
|
|
1468
|
+
],
|
|
1469
|
+
tick: [
|
|
1470
|
+
behavior("rain", "update", { dt: DELTA, splash: gt(PARAM, 0) }),
|
|
1471
|
+
when(eq(PARAM, STORM), [
|
|
1472
|
+
when(gt(TIME, variable("nextStrike")), [set("nextStrike", add(TIME, rnd(3.5, 6))), set("flash", 0)]),
|
|
1473
|
+
when(ge(variable("flash"), 0), [
|
|
1474
|
+
set("flash", add(variable("flash"), DELTA)),
|
|
1475
|
+
set("light", FLASH_STEPS),
|
|
1476
|
+
cue("lightning", { intensity: variable("light") }),
|
|
1477
|
+
screen({ max: { white: mul(variable("light"), 0.12) } }),
|
|
1478
|
+
when(gt(variable("flash"), 0.4), [set("flash", -1), cue("lightning", { intensity: 0 })])
|
|
1479
|
+
]),
|
|
1480
|
+
emit("sheet", "normal", 2.5, { p: [-12, 2.5, rnd(-1, 8)], box: [0, 2, 0], v: [7, -0.5, 0], sp: 0, life: [3, 4], size: [3, 5], grow: 1.3, c0: 9083568, a: 0.06, fi: 0.3 })
|
|
1481
|
+
])
|
|
1482
|
+
]
|
|
1483
|
+
};
|
|
1484
|
+
var CAR_ORIGIN2 = [5.6, 0, 0.8];
|
|
1485
|
+
var CAR_ROTATION2 = [0, -0.4, 0];
|
|
1486
|
+
var carPoint = (x, y, z) => localToWorld(CAR_ORIGIN2, CAR_ROTATION2, [x, y, z]);
|
|
1487
|
+
var carDirection = (from, to) => normalized([to[0] - from[0], to[1] - from[1], to[2] - from[2]]);
|
|
1488
|
+
var BEAM_FROM = carPoint(0, 0.74, 2.15);
|
|
1489
|
+
var BEAM_DIRECTION = carDirection(BEAM_FROM, carPoint(0, 0.74, 3.15));
|
|
1490
|
+
var BEAM_SIDE = [BEAM_DIRECTION[2], 0, -BEAM_DIRECTION[0]];
|
|
1491
|
+
var WALKERS = 6;
|
|
1492
|
+
var WALK_SPEED2 = 0.7;
|
|
1493
|
+
var DROPS2 = 1800;
|
|
1494
|
+
var SLANT2 = 0.8;
|
|
1495
|
+
var startWalking = [
|
|
1496
|
+
set("spot", query("car", "point", rnd(-2, 2), 0, rnd(8, 18))),
|
|
1497
|
+
set("goal", query("car", "point", rnd(-0.6, 0.6), 0, 2.6)),
|
|
1498
|
+
behavior("walkers", "place", { index: INDEX, x: pick(variable("spot"), 0), z: pick(variable("spot"), 2), facing: 0 }),
|
|
1499
|
+
behavior("walkers", "walk", { index: INDEX, to: variable("goal"), speed: WALK_SPEED2 })
|
|
1500
|
+
];
|
|
1501
|
+
var HEADLIGHTS_IN_RAIN = {
|
|
1502
|
+
id: "headlights_in_rain",
|
|
1503
|
+
pageId: "farol",
|
|
1504
|
+
team: "vehicles",
|
|
1505
|
+
budget: { particles: 600, lights: 2 },
|
|
1506
|
+
loop: 0,
|
|
1507
|
+
view: { eye: [-2.5, 2, 5.5], target: [4, 1, 6] },
|
|
1508
|
+
setup: [
|
|
1509
|
+
cue("fog", { density: 0.05 }),
|
|
1510
|
+
cue("headlights", { on: true, intensity: 2.4, color: 16773584 }),
|
|
1511
|
+
behavior("rain", "init", { count: DROPS2, wind: SLANT2 }),
|
|
1512
|
+
repeat(WALKERS, ...startWalking)
|
|
1513
|
+
],
|
|
1514
|
+
timeline: [],
|
|
1515
|
+
tick: [
|
|
1516
|
+
behavior("rain", "update", { dt: DELTA, splash: true }),
|
|
1517
|
+
emit(
|
|
1518
|
+
"lit",
|
|
1519
|
+
"streak",
|
|
1520
|
+
600,
|
|
1521
|
+
local(
|
|
1522
|
+
"depth",
|
|
1523
|
+
rnd(1, 13),
|
|
1524
|
+
local(
|
|
1525
|
+
"spread",
|
|
1526
|
+
mul(variable("depth"), 0.33, sqrt(rand())),
|
|
1527
|
+
local(
|
|
1528
|
+
"turn",
|
|
1529
|
+
rnd(0, 6.283),
|
|
1530
|
+
local("base", vadd(BEAM_FROM, vscale(BEAM_DIRECTION, variable("depth")), vscale(BEAM_SIDE, mul(cos(variable("turn")), variable("spread")))), {
|
|
1531
|
+
p: vwith(variable("base"), 1, add(vy(variable("base")), mul(sin(variable("turn")), variable("spread"), 0.6))),
|
|
1532
|
+
v: [0.8, -14, 0],
|
|
1533
|
+
sp: 0,
|
|
1534
|
+
life: 0.06,
|
|
1535
|
+
len: 0.035,
|
|
1536
|
+
c0: 13622512,
|
|
1537
|
+
a: 0.9
|
|
1538
|
+
})
|
|
1539
|
+
)
|
|
1540
|
+
)
|
|
1541
|
+
)
|
|
1542
|
+
),
|
|
1543
|
+
repeat(WALKERS, when(not(query("walkers", "is_walking", INDEX)), startWalking))
|
|
1544
|
+
]
|
|
1545
|
+
};
|
|
1546
|
+
var YAW = -Math.PI / 2;
|
|
1547
|
+
var COS = Math.cos(YAW);
|
|
1548
|
+
var SIN = Math.sin(YAW);
|
|
1549
|
+
var START_X = 10;
|
|
1550
|
+
var SPEED3 = 2.4;
|
|
1551
|
+
var contactX = (carX) => add(COS * 0.6, 0 * 0.06, SIN * 2.15, carX);
|
|
1552
|
+
var contactZ = add(-SIN * 0.6, 0 * 0.06, COS * 2.15, 1.5);
|
|
1553
|
+
var BACKWARD = normalized([1, 0.35, 0]);
|
|
1554
|
+
var SCRAPING_SPARKS = {
|
|
1555
|
+
id: "scraping_sparks",
|
|
1556
|
+
pageId: "faisca",
|
|
1557
|
+
team: "vehicles",
|
|
1558
|
+
budget: { particles: 200, lights: 1 },
|
|
1559
|
+
loop: 4.4,
|
|
1560
|
+
view: { eye: [2, 1.6, 5.5], target: [3, 0.3, 1.5] },
|
|
1561
|
+
setup: [cue("zombie_visible", { index: -1, visible: false }), cue("car_pose", { x: START_X, z: 1.5, yaw: YAW })],
|
|
1562
|
+
timeline: [],
|
|
1563
|
+
tick: [
|
|
1564
|
+
set("carX", sub(START_X, mul(TIME, SPEED3))),
|
|
1565
|
+
set("contact", [contactX(variable("carX")), 0.04, contactZ]),
|
|
1566
|
+
cue("car_pose", { x: variable("carX"), z: 1.5, yaw: YAW }),
|
|
1567
|
+
emit("sp", "streak", 200, { p: variable("contact"), dir: BACKWARD, cone: 0.55, sp: [3, 8], v: [-2.4, 0, 0], life: [0.2, 0.5], len: 0.02, c0: 16773312, c1: 16732176, g: 9.8, gnd: 2 }),
|
|
1568
|
+
emit("gl", "add", 40, { p: variable("contact"), r: 0.05, size: [0.08, 0.16], life: 0.05, c0: 16767136, fi: 0 }),
|
|
1569
|
+
when(lt(rand(), mul(DELTA, 14)), [decal(vx(variable("contact")), 0, add(vz(variable("contact")), rnd(-0.05, 0.05)), 0.12, 657930, { grow: 0, life: 60, ar: 0.25 })]),
|
|
1570
|
+
fireLight(0, [vx(variable("contact")), 0.34, vz(variable("contact"))], 1.6, mul(TIME, 3))
|
|
1571
|
+
]
|
|
1572
|
+
};
|
|
1573
|
+
var HOOD = carPoint(0, 1.02, 1.4);
|
|
1574
|
+
var EXHAUST = carPoint(0.5, 0.3, -2.2);
|
|
1575
|
+
var EXHAUST_DIRECTION = carDirection(EXHAUST, carPoint(0.5, 0.3, -3));
|
|
1576
|
+
var SPARK_FROM = carPoint(0, 0.7, 2.1);
|
|
1577
|
+
var SPARK_DIRECTION2 = carDirection(SPARK_FROM, carPoint(0, 0.9, 3));
|
|
1578
|
+
var WORN = 1;
|
|
1579
|
+
var BAD = 2;
|
|
1580
|
+
var CRITICAL = 3;
|
|
1581
|
+
var ENGINE_SMOKE = {
|
|
1582
|
+
id: "engine_smoke",
|
|
1583
|
+
pageId: "motor",
|
|
1584
|
+
team: "vehicles",
|
|
1585
|
+
params: { id: "condition", options: ["100", "60", "30", "10"], default: 2 },
|
|
1586
|
+
budget: { particles: 120, lights: 1 },
|
|
1587
|
+
loop: 0,
|
|
1588
|
+
view: { eye: [9.5, 2.6, 5.2], target: [5.2, 0.9, 1.5] },
|
|
1589
|
+
timeline: [],
|
|
1590
|
+
tick: [
|
|
1591
|
+
emit("ex", "normal", ite(eq(PARAM, CRITICAL), 6, 3), { p: EXHAUST, dir: EXHAUST_DIRECTION, cone: 0.3, sp: [0.6, 1.2], drag: 1.2, life: [1, 1.8], size: [0.06, 0.12], grow: 5, c0: ite(gt(PARAM, 1), 5591630, 10132118), a: 0.18, g: -0.2 }),
|
|
1592
|
+
when(eq(PARAM, WORN), [
|
|
1593
|
+
emit("st", "normal", 14, { p: HOOD, box: [0.4, 0, 0.3], dir: [0, 1, 0], cone: 0.35, sp: [0.5, 1], drag: 0.8, life: [1.4, 2.4], size: [0.15, 0.25], grow: 4, c0: 13159632, a: 0.22, g: -0.3 })
|
|
1594
|
+
]),
|
|
1595
|
+
when(eq(PARAM, BAD), [
|
|
1596
|
+
emit("st", "normal", 22, { p: HOOD, box: [0.4, 0, 0.3], dir: [0, 1, 0], cone: 0.35, sp: [0.6, 1.2], drag: 0.6, life: [2, 3], size: [0.2, 0.35], grow: 4, c0: 6974056, c1: 3815996, a: 0.4, g: -0.35 }),
|
|
1597
|
+
when(lt(rand(), mul(DELTA, 0.8)), [burst("streak", 8, { p: SPARK_FROM, dir: SPARK_DIRECTION2, cone: 0.6, sp: [2, 4], life: 0.3, len: 0.02, c0: 16765056, c1: 16728064, g: 9.8 })])
|
|
1598
|
+
]),
|
|
1599
|
+
when(eq(PARAM, CRITICAL), [
|
|
1600
|
+
emit("st", "normal", 34, { p: HOOD, box: [0.5, 0, 0.4], dir: [0, 1, 0], cone: 0.3, sp: [0.8, 1.6], drag: 0.4, life: [2.5, 3.8], size: [0.3, 0.5], grow: 4.5, c0: 1841947, c1: 921104, a: 0.6, g: -0.4 }),
|
|
1601
|
+
call2("fire_emit", "hood", carPoint(0, 0.8, 2), 0.3, 0.45, { noSmoke: true }),
|
|
1602
|
+
fireLight(0, carPoint(0, 1.2, 2.6), 2.2, TIME)
|
|
1603
|
+
], [fireLightOff(0)])
|
|
1604
|
+
]
|
|
1605
|
+
};
|
|
1606
|
+
var UP10 = [0, 1, 0];
|
|
1607
|
+
var doorVelocity = (side) => {
|
|
1608
|
+
const out = carPoint(side * 4, 3, 0.3);
|
|
1609
|
+
const centre = carPoint(0, 0, 0.3);
|
|
1610
|
+
return [out[0] - centre[0], 3, out[2] - centre[2]];
|
|
1611
|
+
};
|
|
1612
|
+
var VEHICLE_BOOM = [
|
|
1613
|
+
call2("explode", vadd(query("car", "position"), [0, 0.6, 0]), 1.8, 2759188),
|
|
1614
|
+
cue("car_burnt"),
|
|
1615
|
+
behavior("car", "launch", { rise: 4.5, spin: 0.9 }),
|
|
1616
|
+
repeat(scaled(30), debris({ p: vadd(query("car", "position"), [0, 1.3, 0]), dir: UP10, cone: 1.3, sp: [2, 6], size: [0.06, 6e-3, 0.06], c: 11061464, life: 20 })),
|
|
1617
|
+
debris({ p: carPoint(0, 1, 1.4), v: [rnd(-1, 1), 9, rnd(-1, 1)], sp: 0, size: [1.6, 0.06, 1.2], c: 3808536, spin: 6, life: 20, bounce: 0.2 }),
|
|
1618
|
+
...[-1, 1].map((side) => debris({ p: carPoint(side * 0.95, 0.7, 0.3), v: doorVelocity(side), sp: 0, size: [0.06, 0.7, 1.1], c: 3808536, spin: 5, life: 20, bounce: 0.2 })),
|
|
1619
|
+
debris({ p: carPoint(0.95, 0.38, 1.35), v: [3, 4, 2], sp: 0, size: [0.3, 0.76, 0.76], c: 1118481, spin: 8, life: 20, bounce: 0.4 })
|
|
1620
|
+
];
|
|
1621
|
+
var TANK = carPoint(-0.6, 0.25, -1.3);
|
|
1622
|
+
var TANK_FLOOR = [TANK[0], 0, TANK[2]];
|
|
1623
|
+
var POOL = [TANK_FLOOR[0] - 1.2, 0, TANK_FLOOR[2] - 0.6];
|
|
1624
|
+
var BOOM_AT = 7.2;
|
|
1625
|
+
var HOLE = carPoint(-0.96, 0.6, -1.2);
|
|
1626
|
+
var FUEL_LEAK = {
|
|
1627
|
+
id: "fuel_leak",
|
|
1628
|
+
pageId: "vazamento",
|
|
1629
|
+
team: "vehicles",
|
|
1630
|
+
budget: { particles: 400, lights: 1 },
|
|
1631
|
+
loop: 11,
|
|
1632
|
+
view: { eye: [10, 2.4, 4.2], target: [5.6, 0.4, 0] },
|
|
1633
|
+
setup: [cue("zombie_visible", { index: -1, visible: false })],
|
|
1634
|
+
timeline: [
|
|
1635
|
+
decal(POOL[0], 0, POOL[2], 2.2, 2040368, { grow: 3, life: 60, ar: 0.6, fluid: "oil" }),
|
|
1636
|
+
after(
|
|
1637
|
+
3.4,
|
|
1638
|
+
call2("impact", "metal", HOLE, carDirection(HOLE, carPoint(-2, 0.6, -1.2)), 1.5),
|
|
1639
|
+
burst("streak", 14, { p: [POOL[0], 0.05, POOL[2]], cone: 1.4, sp: [1, 3], life: 0.3, len: 0.02, c0: 16765056, c1: 16728064, g: 9.8 })
|
|
1640
|
+
),
|
|
1641
|
+
after(BOOM_AT, ...VEHICLE_BOOM)
|
|
1642
|
+
],
|
|
1643
|
+
tick: [
|
|
1644
|
+
when(lt(TIME, BOOM_AT), [
|
|
1645
|
+
emit("drip", "normal", 12, { p: TANK, box: [0.05, 0, 0.05], sp: 0, life: 1, size: 0.03, c0: 5921402, a: 0.9, g: 9.8, fi: 0, gnd: 1 })
|
|
1646
|
+
]),
|
|
1647
|
+
when(and(gt(TIME, 3.5), lt(TIME, BOOM_AT)), [
|
|
1648
|
+
set("spread", clamp(div(sub(TIME, 3.5), 2.5), 0, 1)),
|
|
1649
|
+
set("front", vlerp(POOL, TANK_FLOOR, mul(variable("spread"), 0.8))),
|
|
1650
|
+
call2("fire_emit", "vz", variable("front"), add(0.6, mul(variable("spread"), 0.4)), 1.1, { smoke: 14 }),
|
|
1651
|
+
call2("fire_emit", "vz2", POOL, 0.7, 0.8, { smoke: 6 }),
|
|
1652
|
+
fireLight(0, vadd(variable("front"), [0, 1, 0]), 3, TIME)
|
|
1653
|
+
]),
|
|
1654
|
+
when(ge(TIME, BOOM_AT), [
|
|
1655
|
+
call2("fire_emit", "wr", vadd(query("car", "position"), [0, 0.9, 0]), 0.8, 1.4, { smoke: 18, smokeAlpha: 0.55 }),
|
|
1656
|
+
fireLight(0, vadd(query("car", "position"), [0, 1.6, 0]), 3.4, TIME),
|
|
1657
|
+
behavior("car", "step", { dt: DELTA })
|
|
1658
|
+
])
|
|
1659
|
+
]
|
|
1660
|
+
};
|
|
1661
|
+
var CAR_EXPLOSION = {
|
|
1662
|
+
id: "car_explosion",
|
|
1663
|
+
pageId: "explosao",
|
|
1664
|
+
team: "vehicles",
|
|
1665
|
+
lab: "car_fuel_tank",
|
|
1666
|
+
budget: { particles: 600, debris: 34, lights: 1 },
|
|
1667
|
+
loop: 10,
|
|
1668
|
+
view: { eye: [12, 4.2, 8], target: [5.6, 1, 0.8] },
|
|
1669
|
+
props: ["car"],
|
|
1670
|
+
setup: [cue("zombie_visible", { index: -1, visible: false })],
|
|
1671
|
+
timeline: [after(0.4, ...VEHICLE_BOOM)],
|
|
1672
|
+
tick: [
|
|
1673
|
+
when(gt(TIME, 0.5), [
|
|
1674
|
+
call2("fire_emit", "wr", vadd(query("car", "position"), [0, 0.9, 0]), 0.8, 1.4, { smoke: 18, smokeAlpha: 0.55 }),
|
|
1675
|
+
fireLight(0, vadd(query("car", "position"), [0, 1.6, 0]), 3.4, TIME)
|
|
1676
|
+
]),
|
|
1677
|
+
behavior("car", "step", { dt: DELTA })
|
|
1678
|
+
]
|
|
1679
|
+
};
|
|
1680
|
+
var HITS2 = [[90, 40], [170, 60], [120, 75], [60, 50]];
|
|
1681
|
+
var HIT_X2 = HITS2.map(([x]) => x);
|
|
1682
|
+
var HIT_Y2 = HITS2.map(([, y]) => y);
|
|
1683
|
+
var ZOMBIE = carPoint(0, 0, 3.1);
|
|
1684
|
+
var CAR_YAW = -0.4;
|
|
1685
|
+
var WINDSHIELD = {
|
|
1686
|
+
id: "windshield",
|
|
1687
|
+
pageId: "parabrisa",
|
|
1688
|
+
team: "vehicles",
|
|
1689
|
+
budget: { particles: 6, decals: 1 },
|
|
1690
|
+
loop: 5.8,
|
|
1691
|
+
setup: [
|
|
1692
|
+
cue("zombie_visible", { index: -1, visible: false }),
|
|
1693
|
+
behavior("walkers", "place", { index: 0, x: ZOMBIE[0], z: ZOMBIE[2], facing: CAR_YAW + Math.PI }),
|
|
1694
|
+
camera(carPoint(-0.3, 1.35, -0.2), carPoint(0, 1.2, 2.2), true)
|
|
1695
|
+
],
|
|
1696
|
+
timeline: [
|
|
1697
|
+
repeat(
|
|
1698
|
+
HITS2.length,
|
|
1699
|
+
after(
|
|
1700
|
+
add(0.6, mul(INDEX, 0.85)),
|
|
1701
|
+
cue("zombie_swing", { index: 0, side: mod(INDEX, 2) }),
|
|
1702
|
+
after(
|
|
1703
|
+
add(0.6, mul(INDEX, 0.85), 0.15),
|
|
1704
|
+
behavior("cracks", "crack", { x: pick(HIT_X2, INDEX), y: pick(HIT_Y2, INDEX), big: gt(INDEX, 1) }),
|
|
1705
|
+
when(or(eq(INDEX, 1), eq(INDEX, 3)), [behavior("cracks", "blood_streaks", { x: pick(HIT_X2, INDEX), y: pick(HIT_Y2, INDEX) })]),
|
|
1706
|
+
screen({ add: { shake: 0.18 } }),
|
|
1707
|
+
burst("add", 6, { p: carPoint(-0.1, 1.25, 0.75), box: [0.4, 0.1, 0.05], size: [0.01, 0.03], life: [0.2, 0.5], c0: 16777215, a: 0.8, fi: 0.2 }),
|
|
1708
|
+
cue("windshield_stage", { stage: add(INDEX, 1) })
|
|
1709
|
+
)
|
|
1710
|
+
)
|
|
1711
|
+
)
|
|
1712
|
+
]
|
|
1713
|
+
};
|
|
1714
|
+
var FRESH_BLOOD3 = 9046538;
|
|
1715
|
+
var BEAT_RATE = 1.9;
|
|
1716
|
+
var blow2 = (side) => [
|
|
1717
|
+
cue("zombie_swing", { index: -1, side }),
|
|
1718
|
+
after(
|
|
1719
|
+
add(TIME, 0.18),
|
|
1720
|
+
screen({ set: side === 0 ? { dirL: 1 } : { dirR: 1 }, add: { shake: 0.3 } }),
|
|
1721
|
+
repeat(4, lens(side === 0 ? rnd(0.05, 0.3) : rnd(0.7, 0.95), rnd(0.3, 0.8), rnd(0.02, 0.05), "110,8,8", 0.8)),
|
|
1722
|
+
burst("normal", 12, { p: [0, 1.4, 0.9], dir: [0, 0.2, 1], cone: 0.6, sp: [1, 2], life: 1, size: [0.03, 0.05], c0: FRESH_BLOOD3, g: 9.8, fi: 0, gnd: 3, ds: [0.05, 0.1] })
|
|
1723
|
+
)
|
|
1724
|
+
];
|
|
1725
|
+
var DAMAGE_AND_BITE = {
|
|
1726
|
+
id: "damage_and_bite",
|
|
1727
|
+
pageId: "dano",
|
|
1728
|
+
team: "screen",
|
|
1729
|
+
budget: {},
|
|
1730
|
+
loop: 5.6,
|
|
1731
|
+
view: { eye: [0, 1.6, 1.7], target: [0, 1.5, 0] },
|
|
1732
|
+
timeline: [
|
|
1733
|
+
after(0.3, ...blow2(0)),
|
|
1734
|
+
after(1.6, ...blow2(1)),
|
|
1735
|
+
after(3, cue("zombie_lunge", { z: 0.45 })),
|
|
1736
|
+
after(
|
|
1737
|
+
3.15,
|
|
1738
|
+
screen({ set: { red: 1, desat: 0.9 }, add: { shake: 0.6 } }),
|
|
1739
|
+
cue("bite", { infection: 1 }),
|
|
1740
|
+
repeat(7, lens(rnd(0.2, 0.8), rnd(0.2, 0.7), rnd(0.04, 0.1), "100,6,6", 1))
|
|
1741
|
+
)
|
|
1742
|
+
],
|
|
1743
|
+
tick: [
|
|
1744
|
+
when(and(gt(TIME, 3.2), lt(TIME, 5.4)), [when(lt(mod(mul(TIME, BEAT_RATE), 1), mul(DELTA, BEAT_RATE)), [screen({ set: { beat: 1 } })])])
|
|
1745
|
+
]
|
|
1746
|
+
};
|
|
1747
|
+
var MALAISE = 0;
|
|
1748
|
+
var FEVER = 1;
|
|
1749
|
+
var DELIRIUM = 2;
|
|
1750
|
+
var LAST_HOURS = 3;
|
|
1751
|
+
var GHOSTS = [[-3, -1.8], [3.5, -2.4], [-6, 1.5]];
|
|
1752
|
+
var INFECTION_PHASES = {
|
|
1753
|
+
id: "infection_phases",
|
|
1754
|
+
pageId: "infeccao",
|
|
1755
|
+
team: "screen",
|
|
1756
|
+
params: { id: "phase", options: ["malaise", "fever", "delirium", "last_hours"], default: 1 },
|
|
1757
|
+
budget: { particles: 10 },
|
|
1758
|
+
loop: 0,
|
|
1759
|
+
view: { eye: [2, 1.7, 7], target: [0, 1.2, -1] },
|
|
1760
|
+
setup: [
|
|
1761
|
+
cue("zombie_visible", { index: -1, visible: false }),
|
|
1762
|
+
...GHOSTS.map(([x, z], index) => cue("ghost_place", { index, x, z, turn: rnd(-0.4, 0.4) }))
|
|
1763
|
+
],
|
|
1764
|
+
timeline: [set("nextCough", 2)],
|
|
1765
|
+
tick: [
|
|
1766
|
+
when(eq(PARAM, MALAISE), [post({ desat: 0.25, tunnel: add(0.15, mul(0.12, sin(mul(TIME, 1.2)))), blur: mul(0.3, max(0, sin(mul(TIME, 0.7)))) })]),
|
|
1767
|
+
when(eq(PARAM, FEVER), [
|
|
1768
|
+
post({ cold: add(0.8, mul(0.15, sin(mul(TIME, 2)))), blur: add(0.6, mul(0.6, sin(mul(TIME, 1.6)))), desat: 0.3 }),
|
|
1769
|
+
when(gt(TIME, variable("nextCough")), [
|
|
1770
|
+
set("nextCough", add(TIME, rnd(3, 5))),
|
|
1771
|
+
screen({ add: { shake: 0.25 } }),
|
|
1772
|
+
burst("normal", 10, { p: vadd(CAMERA_POSITION, cameraForward([0, -0.15, -0.6])), dir: cameraForward([0, 0, -1]), cone: 0.4, sp: [0.6, 1.2], drag: 1.5, life: 1.2, size: [0.05, 0.1], grow: 5, c0: 14673646, a: 0.2 })
|
|
1773
|
+
])
|
|
1774
|
+
]),
|
|
1775
|
+
when(eq(PARAM, DELIRIUM), [
|
|
1776
|
+
post({ chroma: add(2, mul(3, add(0.5, mul(0.5, sin(mul(TIME, 1.7)))))), hue: mul(22, sin(mul(TIME, 0.6))), tunnel: 0.3, desat: 0.15 }),
|
|
1777
|
+
repeat(GHOSTS.length, cue("ghost_visible", { index: INDEX, visible: gt(sin(add(mul(TIME, add(1.3, mul(INDEX, 0.7))), mul(INDEX, 2))), 0.6) })),
|
|
1778
|
+
when(lt(rand(), mul(DELTA, 0.3)), [screen({ set: { white: 0.12 } })])
|
|
1779
|
+
]),
|
|
1780
|
+
when(eq(PARAM, LAST_HOURS), [
|
|
1781
|
+
post({ desat: 0.85, tintAlpha: 0.22, tintColor: "70,110,40", tunnel: 0.55, blur: 1.2 }),
|
|
1782
|
+
when(lt(mod(mul(TIME, 2.2), 1), mul(DELTA, 2.2)), [screen({ set: { beat: 1 }, add: { shake: 0.05 } })])
|
|
1783
|
+
])
|
|
1784
|
+
]
|
|
1785
|
+
};
|
|
1786
|
+
var WALKERS2 = 6;
|
|
1787
|
+
var NEAR = 9;
|
|
1788
|
+
var RANGE = 7;
|
|
1789
|
+
var RESTING_BPM = 70;
|
|
1790
|
+
var BPM_RISE = 80;
|
|
1791
|
+
var walkerPoint = [query("walkers", "x", INDEX), 0, query("walkers", "z", INDEX)];
|
|
1792
|
+
var PANIC = {
|
|
1793
|
+
id: "panic",
|
|
1794
|
+
pageId: "panico",
|
|
1795
|
+
team: "screen",
|
|
1796
|
+
budget: {},
|
|
1797
|
+
loop: 8,
|
|
1798
|
+
view: { eye: [0, 1.65, 6], target: [0, 1.3, -2] },
|
|
1799
|
+
setup: [
|
|
1800
|
+
cue("zombie_visible", { index: -1, visible: false }),
|
|
1801
|
+
repeat(
|
|
1802
|
+
WALKERS2,
|
|
1803
|
+
set("startX", rnd(-4, 4)),
|
|
1804
|
+
set("startZ", sub(rnd(-4, -2), mul(INDEX, 0.6))),
|
|
1805
|
+
behavior("walkers", "place", { index: INDEX, x: variable("startX"), z: variable("startZ"), facing: 0 }),
|
|
1806
|
+
behavior("walkers", "walk", { index: INDEX, to: [rnd(-1.2, 1.2), 0, 5], speed: ite(eq(mod(INDEX, 3), 1), 1.6, 0.7) })
|
|
1807
|
+
)
|
|
1808
|
+
],
|
|
1809
|
+
timeline: [],
|
|
1810
|
+
tick: [
|
|
1811
|
+
set("nearest", 99),
|
|
1812
|
+
repeat(WALKERS2, set("nearest", min(variable("nearest"), vdist(walkerPoint, CAMERA_POSITION)))),
|
|
1813
|
+
set("fear", clamp(div(sub(NEAR, variable("nearest")), RANGE), 0, 1)),
|
|
1814
|
+
set("bpm", add(RESTING_BPM, mul(BPM_RISE, variable("fear")))),
|
|
1815
|
+
when(lt(mod(div(mul(TIME, variable("bpm")), 60), 1), div(mul(DELTA, variable("bpm")), 60)), [screen({ set: { beat: add(0.4, mul(0.6, variable("fear"))) } })]),
|
|
1816
|
+
post({ tunnel: add(0.1, mul(0.65, variable("fear"))), desat: mul(0.45, variable("fear")) }),
|
|
1817
|
+
set("tremor", add(0.012, mul(0.035, variable("fear"))))
|
|
1818
|
+
]
|
|
1819
|
+
};
|
|
1820
|
+
var BLOATER_BLINDNESS = {
|
|
1821
|
+
id: "bloater_blindness",
|
|
1822
|
+
pageId: "cegueira",
|
|
1823
|
+
team: "screen",
|
|
1824
|
+
budget: { particles: 30 },
|
|
1825
|
+
loop: 7.5,
|
|
1826
|
+
view: { eye: [0, 1.6, 2.6], target: [0, 1.3, 0] },
|
|
1827
|
+
setup: [cue("bloater_pose", { eyes: 6283402, skin: 7043666, belly: [1.4, 1.25, 1.6] })],
|
|
1828
|
+
timeline: [
|
|
1829
|
+
after(
|
|
1830
|
+
0.7,
|
|
1831
|
+
cue("zombie_visible", { index: -1, visible: false }),
|
|
1832
|
+
screen({ set: { gas: 1 }, add: { shake: 0.3 } }),
|
|
1833
|
+
burst("normal", 30, { p: [0, 1.3, 0.8], r: 0.6, sp: [0.5, 2], drag: 2, life: [3, 5], size: [0.8, 1.6], grow: 1.6, c0: 7309884, c1: 3885606, a: 0.3, fi: 0.05 }),
|
|
1834
|
+
repeat(8, lens(rnd(0.15, 0.85), rnd(0.15, 0.7), rnd(0.03, 0.08), "110,150,50", 0.9))
|
|
1835
|
+
),
|
|
1836
|
+
after(2, screen({ add: { shake: 0.2 } })),
|
|
1837
|
+
after(3.4, screen({ add: { shake: 0.2 } }))
|
|
1838
|
+
]
|
|
1839
|
+
};
|
|
1840
|
+
var FIRE = [-1.4, 0.1, 3];
|
|
1841
|
+
var CAMPFIRE = {
|
|
1842
|
+
id: "campfire",
|
|
1843
|
+
pageId: "fogueira",
|
|
1844
|
+
team: "screen",
|
|
1845
|
+
budget: { particles: 120, lights: 1 },
|
|
1846
|
+
loop: 0,
|
|
1847
|
+
view: { eye: [1.4, 1.6, 6.4], target: [-1.4, 0.6, 3] },
|
|
1848
|
+
setup: [cue("zombie_visible", { index: -1, visible: false }), cue("survivor_pose", { x: -2.6, z: 3.6, turn: 2.2 })],
|
|
1849
|
+
timeline: [],
|
|
1850
|
+
tick: [
|
|
1851
|
+
call2("fire_emit", "camp", FIRE, 0.25, 0.55, { smoke: 8, smokeColor: 4867650, smokeAlpha: 0.25 }),
|
|
1852
|
+
fireLight(0, [FIRE[0], FIRE[1] + 0.8, FIRE[2]], 2.4, TIME)
|
|
1853
|
+
]
|
|
1854
|
+
};
|
|
1855
|
+
var FACING3 = 0.5;
|
|
1856
|
+
var MOUTH = [Math.sin(FACING3) * 0.2 + -1.6, 1.68, Math.cos(FACING3) * 0.2 + 1.8];
|
|
1857
|
+
var BREATH = normalized([Math.sin(FACING3), -0.15, Math.cos(FACING3)]);
|
|
1858
|
+
var BREATH_EVERY = 2.4;
|
|
1859
|
+
var COUGH_EVERY = 6.5;
|
|
1860
|
+
var puff = (strength) => burst("normal", 8 * strength, { p: MOUTH, dir: BREATH, cone: 0.35, sp: [0.5, 1.1 * strength], drag: 1.6, life: [1.2, 1.8], size: [0.05, 0.09], grow: 6, c0: 14673646, a: 0.22, g: -0.1 });
|
|
1861
|
+
var COUGH_AND_BREATH = {
|
|
1862
|
+
id: "cough_and_breath",
|
|
1863
|
+
pageId: "tosse",
|
|
1864
|
+
team: "screen",
|
|
1865
|
+
budget: { particles: 40, lights: 1 },
|
|
1866
|
+
loop: 0,
|
|
1867
|
+
view: { eye: [2.4, 1.8, 6.5], target: [-1.4, 1.3, 1.6] },
|
|
1868
|
+
setup: [cue("zombie_visible", { index: -1, visible: false }), cue("survivor_pose", { x: -1.6, z: 1.8, turn: FACING3 }), cue("torch", { on: true })],
|
|
1869
|
+
timeline: [set("nextBreath", 0.5), set("nextCough", 3)],
|
|
1870
|
+
tick: [
|
|
1871
|
+
when(gt(TIME, variable("nextBreath")), [set("nextBreath", add(TIME, BREATH_EVERY)), puff(1)]),
|
|
1872
|
+
when(gt(TIME, variable("nextCough")), [
|
|
1873
|
+
set("nextCough", add(TIME, COUGH_EVERY)),
|
|
1874
|
+
...[0, 0.25, 0.5].map((delay) => after(add(TIME, delay), puff(1.6), cue("survivor_jolt", { tilt: 0.25 })))
|
|
1875
|
+
])
|
|
1876
|
+
]
|
|
1877
|
+
};
|
|
1878
|
+
var FACING4 = [0, 0, 1];
|
|
1879
|
+
var UP11 = [0, 1, 0];
|
|
1880
|
+
var ORIGIN = [0, 0, 0];
|
|
1881
|
+
var FORWARD4 = [0, 0, -1];
|
|
1882
|
+
var IMPACT_MATERIALS = ["concrete", "metal", "wood", "glass", "flesh", "water"];
|
|
1883
|
+
var impactEffect = (material) => ({
|
|
1884
|
+
id: `impact_${material}`,
|
|
1885
|
+
pageId: `event:impact_${material}`,
|
|
1886
|
+
team: "weapons",
|
|
1887
|
+
budget: { particles: 40, decals: 1 },
|
|
1888
|
+
loop: 2,
|
|
1889
|
+
timeline: [call2("impact", material, ORIGIN, FACING4, 1, 0)]
|
|
1890
|
+
});
|
|
1891
|
+
var muzzleEffect = (weapon) => ({
|
|
1892
|
+
id: `muzzle_${weapon}`,
|
|
1893
|
+
pageId: `event:muzzle_${weapon}`,
|
|
1894
|
+
team: "weapons",
|
|
1895
|
+
budget: { particles: 60, lights: 1 },
|
|
1896
|
+
loop: 2.4,
|
|
1897
|
+
timeline: [call2("muzzle", weapon, ORIGIN, FORWARD4)]
|
|
1898
|
+
});
|
|
1899
|
+
var casingEffect = (id, type) => ({
|
|
1900
|
+
id,
|
|
1901
|
+
pageId: `event:${id}`,
|
|
1902
|
+
team: "weapons",
|
|
1903
|
+
budget: { debris: 1 },
|
|
1904
|
+
loop: 2,
|
|
1905
|
+
timeline: [call2("casing", ORIGIN, type)]
|
|
1906
|
+
});
|
|
1907
|
+
var EVENT_EFFECTS = [
|
|
1908
|
+
...IMPACT_MATERIALS.map(impactEffect),
|
|
1909
|
+
...["glock", "ak", "r870", "barrett"].map(muzzleEffect),
|
|
1910
|
+
casingEffect("casing_brass", ""),
|
|
1911
|
+
casingEffect("casing_shell", "shell"),
|
|
1912
|
+
casingEffect("casing_50", "50"),
|
|
1913
|
+
{
|
|
1914
|
+
// door_stages (W856-871): the dust a blow shakes loose from the frame and the splinters.
|
|
1915
|
+
id: "stage_crack",
|
|
1916
|
+
pageId: "event:stage_crack",
|
|
1917
|
+
team: "destruction",
|
|
1918
|
+
budget: { particles: 12, debris: 5 },
|
|
1919
|
+
loop: 2,
|
|
1920
|
+
timeline: [
|
|
1921
|
+
burst("normal", 12, { p: ORIGIN, box: [0.6, 0.05, 0.02], dir: [0, -0.287, 0.958], cone: 0.6, sp: [0.2, 0.8], drag: 1.5, life: [0.8, 1.4], size: [0.08, 0.16], grow: 3, c0: 8024934, a: 0.45, g: 0.4 }),
|
|
1922
|
+
repeat(scaled(2), debris({ p: [rnd(-0.5, 0.5), rnd(0, 1.6), 0], dir: [0, 0.287, 0.958], cone: 0.6, sp: [1, 2.5], size: [0.015, 0.015, 0.1], c: 8017200, life: 12 }))
|
|
1923
|
+
]
|
|
1924
|
+
},
|
|
1925
|
+
{
|
|
1926
|
+
// block_wall (W872-886, 3.6 s): the ring of dust that rolls out when the wall gives way.
|
|
1927
|
+
id: "breach_dust",
|
|
1928
|
+
pageId: "event:breach_dust",
|
|
1929
|
+
team: "destruction",
|
|
1930
|
+
budget: { particles: 90, debris: 16 },
|
|
1931
|
+
loop: 5,
|
|
1932
|
+
timeline: [
|
|
1933
|
+
screen({ add: { shake: 0.25 } }),
|
|
1934
|
+
burst("normal", 30, { p: ORIGIN, box: [1.4, 0.8, 0.2], sp: [0.3, 1.2], drag: 1.5, life: [1.5, 2.6], size: [0.4, 0.7], grow: 3, c0: 9078138, c1: 4867648, a: 0.45 }),
|
|
1935
|
+
repeat(scaled(16), debris({ p: ORIGIN, box: [1.3, 0.8, 0.1], sp: [1, 3], size: [0.08, 0.07, 0.08], k: [0.5, 1.5], c: 7236195, life: 20 })),
|
|
1936
|
+
repeat(
|
|
1937
|
+
scaled(60),
|
|
1938
|
+
spawn("normal", local("angle", rnd(0, 6.283), {
|
|
1939
|
+
p: [rnd(-1.4, 1.4), 0.2, rnd(-0.6, 0.4)],
|
|
1940
|
+
dir: vnorm([cos(variable("angle")), 0.3, sin(variable("angle"))]),
|
|
1941
|
+
cone: 0.4,
|
|
1942
|
+
sp: [0.8, 2.4],
|
|
1943
|
+
drag: 1.3,
|
|
1944
|
+
life: [2.5, 4.5],
|
|
1945
|
+
size: [0.6, 1],
|
|
1946
|
+
grow: 3,
|
|
1947
|
+
c0: 8024680,
|
|
1948
|
+
c1: 4867648,
|
|
1949
|
+
a: 0.45,
|
|
1950
|
+
fi: 0.12
|
|
1951
|
+
}))
|
|
1952
|
+
)
|
|
1953
|
+
]
|
|
1954
|
+
},
|
|
1955
|
+
{
|
|
1956
|
+
// building_collapse (W872-886): the slab dropping in blocks and the cloud that rolls along the street.
|
|
1957
|
+
id: "collapse_dust",
|
|
1958
|
+
pageId: "event:collapse_dust",
|
|
1959
|
+
team: "destruction",
|
|
1960
|
+
budget: { particles: 350, debris: 26 },
|
|
1961
|
+
loop: 8,
|
|
1962
|
+
timeline: [
|
|
1963
|
+
screen({ add: { shake: 0.45 } }),
|
|
1964
|
+
repeat(6, debris({ p: ORIGIN, box: [2, 0.05, 0.6], v: [rnd(-0.5, 0.5), rnd(-0.5, 0), rnd(0, 0.8)], sp: 0, size: [rnd(0.5, 1.1), 0.25, rnd(0.4, 0.8)], c: 7236195, spin: 3, life: 30, bounce: 0.1 })),
|
|
1965
|
+
repeat(scaled(20), debris({ p: ORIGIN, box: [2.1, 0.1, 0.7], v: [rnd(-1, 1), rnd(-1, 1), rnd(0, 1.5)], sp: 0, size: [0.12, 0.1, 0.12], k: [0.5, 1.5], c: 6183508, life: 30 })),
|
|
1966
|
+
repeat(
|
|
1967
|
+
scaled(70),
|
|
1968
|
+
spawn("normal", local("angle", rnd(-0.4, 3.5), {
|
|
1969
|
+
p: [rnd(-2, 2), 0.2, rnd(-0.5, 0.5)],
|
|
1970
|
+
dir: vnorm([mul(cos(variable("angle")), 0.6), 0.25, sin(variable("angle"))]),
|
|
1971
|
+
cone: 0.5,
|
|
1972
|
+
sp: [1, 3.2],
|
|
1973
|
+
drag: 1.1,
|
|
1974
|
+
life: [3, 6],
|
|
1975
|
+
size: [0.7, 1.2],
|
|
1976
|
+
grow: 3,
|
|
1977
|
+
c0: 8024680,
|
|
1978
|
+
c1: 4867648,
|
|
1979
|
+
a: 0.5,
|
|
1980
|
+
fi: 0.12
|
|
1981
|
+
}))
|
|
1982
|
+
)
|
|
1983
|
+
]
|
|
1984
|
+
},
|
|
1985
|
+
{
|
|
1986
|
+
// shopfront_glass (W846-855): the pane coming down as shards, the flash of the glints and the pale dust.
|
|
1987
|
+
id: "glass_burst",
|
|
1988
|
+
pageId: "event:glass_burst",
|
|
1989
|
+
team: "destruction",
|
|
1990
|
+
budget: { debris: 80, particles: 50 },
|
|
1991
|
+
loop: 5,
|
|
1992
|
+
timeline: [
|
|
1993
|
+
screen({ add: { shake: 0.08 } }),
|
|
1994
|
+
repeat(
|
|
1995
|
+
scaled(75),
|
|
1996
|
+
debris({ p: ORIGIN, box: [1.25, 0.85, 0.02], v: [rnd(-0.4, 0.4), rnd(-0.5, 0.8), rnd(0.6, 2)], sp: 0, size: [rnd(0.05, 0.18), 6e-3, rnd(0.05, 0.18)], c: 11061464, spin: 14, life: 30, bounce: 0.15 })
|
|
1997
|
+
),
|
|
1998
|
+
burst("add", 30, { p: ORIGIN, box: [1.2, 0.8, 0.05], size: [0.02, 0.05], life: [0.2, 0.6], c0: 16777215, a: 0.9, fi: 0.3 }),
|
|
1999
|
+
burst("normal", 20, { p: [0, -0.6, 0.1], box: [1.2, 0.5, 0.1], sp: [0.2, 0.6], drag: 2, life: [0.8, 1.4], size: [0.12, 0.2], grow: 3, c0: 12572386, a: 0.2 })
|
|
2000
|
+
]
|
|
2001
|
+
},
|
|
2002
|
+
{
|
|
2003
|
+
// The chips macro the page uses on wood (W849) plus rust (`rustAt`), for rebar laid bare in concrete.
|
|
2004
|
+
id: "rebar_expose",
|
|
2005
|
+
pageId: "event:rebar_expose",
|
|
2006
|
+
team: "destruction",
|
|
2007
|
+
budget: { particles: 20, debris: 8 },
|
|
2008
|
+
loop: 2,
|
|
2009
|
+
timeline: [call2("chips", ORIGIN, UP11, 8, 0.9), call2("rust_at", ORIGIN, 6)]
|
|
2010
|
+
}
|
|
2011
|
+
];
|
|
2012
|
+
var PI = Math.PI;
|
|
2013
|
+
var SMOKE = { color: 9079430, width: 10, height: 8, gravity: -0.08, drag: 2.2, growth: 2.1 };
|
|
2014
|
+
var FLASH_SECONDS = 0.055;
|
|
2015
|
+
var FLASH_RAMP = [0.6, 0.9];
|
|
2016
|
+
var FLASH_OPACITY = 0.95;
|
|
2017
|
+
var FLAME_COLORS = [16742946, 16760896, 13121050, 16773296];
|
|
2018
|
+
var FLAME_ADDITIVE = 3;
|
|
2019
|
+
var ORIGIN2 = [0, 0, 0];
|
|
2020
|
+
var SIZE = variable("size");
|
|
2021
|
+
var wide = (width) => mul(sub(rand(), 0.5), width);
|
|
2022
|
+
var puff2 = (point, velocity, world, radius, life, opacity) => mesh({
|
|
2023
|
+
shape: "sphere",
|
|
2024
|
+
p: point,
|
|
2025
|
+
v: velocity,
|
|
2026
|
+
wv: world,
|
|
2027
|
+
r: radius,
|
|
2028
|
+
seg: SMOKE.width,
|
|
2029
|
+
seg2: SMOKE.height,
|
|
2030
|
+
life,
|
|
2031
|
+
c0: SMOKE.color,
|
|
2032
|
+
a: opacity,
|
|
2033
|
+
fade: true,
|
|
2034
|
+
lit: true,
|
|
2035
|
+
g: SMOKE.gravity,
|
|
2036
|
+
drag: SMOKE.drag,
|
|
2037
|
+
grow: SMOKE.growth
|
|
2038
|
+
});
|
|
2039
|
+
var flameBit = (point, velocity, world, radius, life) => [
|
|
2040
|
+
set("bitPoint", point),
|
|
2041
|
+
set("bitVelocity", velocity),
|
|
2042
|
+
set("bitWorld", world),
|
|
2043
|
+
set("bitRadius", radius),
|
|
2044
|
+
set("bitLife", life),
|
|
2045
|
+
set("bitColour", floor(mul(rand(), FLAME_COLORS.length))),
|
|
2046
|
+
mesh({
|
|
2047
|
+
shape: "icosahedron",
|
|
2048
|
+
p: variable("bitPoint"),
|
|
2049
|
+
v: variable("bitVelocity"),
|
|
2050
|
+
wv: variable("bitWorld"),
|
|
2051
|
+
r: variable("bitRadius"),
|
|
2052
|
+
seg: 1,
|
|
2053
|
+
rot: [mul(rand(), 3), mul(rand(), 3), 0],
|
|
2054
|
+
spin: [3, 4, 2],
|
|
2055
|
+
life: variable("bitLife"),
|
|
2056
|
+
c0: pick(FLAME_COLORS, variable("bitColour")),
|
|
2057
|
+
add: eq(variable("bitColour"), FLAME_ADDITIVE),
|
|
2058
|
+
a: 0.9,
|
|
2059
|
+
fade: true,
|
|
2060
|
+
g: -1.4,
|
|
2061
|
+
drag: 1.4,
|
|
2062
|
+
grow: 2.2
|
|
2063
|
+
})
|
|
2064
|
+
];
|
|
2065
|
+
var flashPiece = (shape, radius, height, width, at3, rot, color) => mesh({ shape, r: radius, ...height === void 0 ? {} : { h: height }, seg: width, seg2: shape === "sphere" ? 8 : 1, p: ORIGIN2, at: at3, rot, roll: variable("roll"), ramp: FLASH_RAMP, life: FLASH_SECONDS, c0: color, a: FLASH_OPACITY, add: true });
|
|
2066
|
+
var MUZZLE_FLASH2 = {
|
|
2067
|
+
id: "viewmodel_muzzle_flash",
|
|
2068
|
+
pageId: "event:viewmodel_muzzle_flash",
|
|
2069
|
+
team: "weapons",
|
|
2070
|
+
budget: { particles: 12, lights: 1 },
|
|
2071
|
+
loop: 0.1,
|
|
2072
|
+
timeline: [
|
|
2073
|
+
set("angles", []),
|
|
2074
|
+
repeat(4, append("angles", add(div(mul(INDEX, PI), 2), mul(rand(), 0.6)))),
|
|
2075
|
+
set("roll", mul(rand(), PI)),
|
|
2076
|
+
flash(ORIGIN2, 16756832, mul(4, SIZE), FLASH_SECONDS, mul(2, SIZE), true, true),
|
|
2077
|
+
flashPiece("cone_open", mul(0.013, SIZE), mul(0.085, SIZE), 10, [mul(0.042, SIZE), 0, 0], [0, 0, -PI / 2], 16757575),
|
|
2078
|
+
repeat(
|
|
2079
|
+
4,
|
|
2080
|
+
set("angle", pick(variable("angles"), INDEX)),
|
|
2081
|
+
flashPiece(
|
|
2082
|
+
"cone",
|
|
2083
|
+
mul(5e-3, SIZE),
|
|
2084
|
+
mul(0.04, SIZE),
|
|
2085
|
+
6,
|
|
2086
|
+
[mul(0.012, SIZE), mul(cos(variable("angle")), 0.016, SIZE), mul(sin(variable("angle")), 0.016, SIZE)],
|
|
2087
|
+
[variable("angle"), 0, -PI / 2],
|
|
2088
|
+
16757575
|
|
2089
|
+
)
|
|
2090
|
+
),
|
|
2091
|
+
flashPiece("sphere", mul(0.016, SIZE), void 0, 12, [mul(8e-3, SIZE), 0, 0], [0, 0, 0], 16773568),
|
|
2092
|
+
repeat(
|
|
2093
|
+
6,
|
|
2094
|
+
puff2(
|
|
2095
|
+
ORIGIN2,
|
|
2096
|
+
[add(0.15, mul(rand(), 0.35)), add(0.03, mul(rand(), 0.12)), mul(sub(rand(), 0.5), 0.14)],
|
|
2097
|
+
[0, 0, 0],
|
|
2098
|
+
mul(0.013, SIZE),
|
|
2099
|
+
add(1.3, mul(rand(), 0.6)),
|
|
2100
|
+
0.45
|
|
2101
|
+
)
|
|
2102
|
+
)
|
|
2103
|
+
]
|
|
2104
|
+
};
|
|
2105
|
+
var SMOKE_PUFF = {
|
|
2106
|
+
id: "weapon_smoke_puff",
|
|
2107
|
+
pageId: "event:weapon_smoke_puff",
|
|
2108
|
+
team: "weapons",
|
|
2109
|
+
budget: { particles: 1 },
|
|
2110
|
+
loop: 0.1,
|
|
2111
|
+
timeline: [puff2(ORIGIN2, void 0, [variable("vx"), variable("vy"), variable("vz")], variable("radius"), variable("life"), variable("opacity"))]
|
|
2112
|
+
};
|
|
2113
|
+
var BACKBLAST = {
|
|
2114
|
+
id: "launcher_backblast",
|
|
2115
|
+
pageId: "event:launcher_backblast",
|
|
2116
|
+
team: "weapons",
|
|
2117
|
+
budget: { particles: 40 },
|
|
2118
|
+
loop: 0.1,
|
|
2119
|
+
timeline: [
|
|
2120
|
+
repeat(26, puff2(ORIGIN2, [neg(add(1.5, mul(rand(), 3))), 0, 0], [wide(1.4), wide(0.8), wide(1.4)], add(0.03, mul(rand(), 0.03)), add(1.8, mul(rand(), 1.4)), 0.5)),
|
|
2121
|
+
repeat(14, ...flameBit(ORIGIN2, [neg(add(2, mul(rand(), 2))), 0, 0], [wide(1), wide(0.6), wide(1)], 0.02, 0.25))
|
|
2122
|
+
]
|
|
2123
|
+
};
|
|
2124
|
+
var FLAME_JET = {
|
|
2125
|
+
id: "flame_jet",
|
|
2126
|
+
pageId: "event:flame_jet",
|
|
2127
|
+
team: "weapons",
|
|
2128
|
+
budget: { particles: 30 },
|
|
2129
|
+
loop: 0.1,
|
|
2130
|
+
timeline: [
|
|
2131
|
+
repeat(
|
|
2132
|
+
floor(mul(420, variable("dt"), variable("scale"))),
|
|
2133
|
+
set("speed", mul(add(2.2, mul(rand(), 1.1)), variable("scale"))),
|
|
2134
|
+
...flameBit(
|
|
2135
|
+
[mul(rand(), variable("speed"), min(variable("dt"), 0.3)), 0, 0],
|
|
2136
|
+
[variable("speed"), 0, 0],
|
|
2137
|
+
[wide(0.35), mul(sub(rand(), 0.3), 0.3), wide(0.35)],
|
|
2138
|
+
add(0.02, mul(rand(), 0.022)),
|
|
2139
|
+
add(0.4, mul(rand(), 0.35))
|
|
2140
|
+
)
|
|
2141
|
+
),
|
|
2142
|
+
when(lt(rand(), 0.5), [
|
|
2143
|
+
puff2([add(mul(1.1, variable("scale")), mul(rand(), 0.4)), 0, 0], void 0, [mul(vx(DIRECTION), 0.6), 0.35, mul(vz(DIRECTION), 0.6)], 0.03, 1.6, 0.4)
|
|
2144
|
+
])
|
|
2145
|
+
]
|
|
2146
|
+
};
|
|
2147
|
+
var VIEWMODEL_EFFECTS = [MUZZLE_FLASH2, SMOKE_PUFF, BACKBLAST, FLAME_JET];
|
|
2148
|
+
var aliasOf = (base, id, changes) => ({ ...base, id, pageId: `vehicle:${id}`, anchor: CAR_ORIGIN2, ...changes });
|
|
2149
|
+
var VEHICLE_EFFECTS = [
|
|
2150
|
+
/** The engine on fire: `engine_smoke` at its worst condition (black smoke, flames in the hood, a light). */
|
|
2151
|
+
aliasOf(ENGINE_SMOKE, "vehicle_fire", { params: { id: "condition", options: ["100", "60", "30", "10"], default: 3 }, loop: 12 }),
|
|
2152
|
+
/** The exhaust of a car under way: `engine_smoke` in the best condition, for half a second so a moving car asks again. */
|
|
2153
|
+
aliasOf(ENGINE_SMOKE, "vehicle_exhaust", { params: { id: "condition", options: ["100", "60", "30", "10"], default: 0 }, loop: 0.5 }),
|
|
2154
|
+
/** A hole in the tank: the page's own petrol leak (drips, pool, sparks, fire running to the tank). */
|
|
2155
|
+
aliasOf(FUEL_LEAK, "vehicle_leak", {})
|
|
2156
|
+
];
|
|
2157
|
+
var ALL_EFFECTS = [BLOOD_HIT, HEADSHOT, DISMEMBER, BLOATER_CLOUD, SCREAMER_SHRIEK, CORPSE_DECAY, REANIMATION, EYES_IN_FOG, MUZZLE_FLASH, IMPACT_BY_MATERIAL, PENETRATION, CASINGS_AND_MAGAZINE, MOLOTOV, GRENADE, EXPLOSIVE_BARREL, SHOPFRONT_GLASS, DOOR_STAGES, BUILDING_COLLAPSE, BLOCK_WALL, METAL_DOOR_EFFECT, IRON_RAILING, WOODEN_FENCE, HIT_POINT_BREAKAGE, PRESSURE_CYLINDERS, BUILDING_FIRE, RAIN_AND_PUDDLES, FOG_AND_ASH, SCRAPING_SPARKS, ENGINE_SMOKE, FUEL_LEAK, CAR_EXPLOSION, WINDSHIELD, HEADLIGHTS_IN_RAIN, DAMAGE_AND_BITE, INFECTION_PHASES, PANIC, BLOATER_BLINDNESS, CAMPFIRE, COUGH_AND_BREATH];
|
|
2158
|
+
var WORKSHOP_EFFECTS = Object.fromEntries(ALL_EFFECTS.map((effect) => [effect.id, effect]));
|
|
2159
|
+
var GAME_EFFECTS = { ...WORKSHOP_EFFECTS, ...Object.fromEntries([...EVENT_EFFECTS, ...VIEWMODEL_EFFECTS, ...VEHICLE_EFFECTS].map((effect) => [effect.id, effect])) };
|
|
2160
|
+
var QUARTER_TURN2 = Math.PI / 2;
|
|
2161
|
+
var SCRATCH = createVec3();
|
|
2162
|
+
var QUARTER_TURN3 = Math.PI / 2;
|
|
2163
|
+
|
|
2164
|
+
// src/rain-near.ts
|
|
2165
|
+
var SPLASH_FROM_MM = 5;
|
|
2166
|
+
function createNearRain(vfx, options = {}) {
|
|
2167
|
+
const puddles = options.puddles ?? [];
|
|
2168
|
+
return {
|
|
2169
|
+
update(sample, dt, camera2) {
|
|
2170
|
+
const raining = sample.rain > 0;
|
|
2171
|
+
const engine = raining ? vfx?.workshop() : vfx?.peekWorkshop();
|
|
2172
|
+
if (!engine) return;
|
|
2173
|
+
const field = engine.rain;
|
|
2174
|
+
if (!raining) {
|
|
2175
|
+
if (field.on) field.clear();
|
|
2176
|
+
return;
|
|
2177
|
+
}
|
|
2178
|
+
field.puddleAt = options.puddleAt ?? ((x, z) => inPuddle(puddles, x, z));
|
|
2179
|
+
field.drive(sample.drops, sample.windX, camera2[0], camera2[2]);
|
|
2180
|
+
field.update(dt, sample.rain >= (options.splashFrom ?? SPLASH_FROM_MM), camera2);
|
|
2181
|
+
},
|
|
2182
|
+
count: () => vfx?.peekWorkshop()?.rain.count ?? 0,
|
|
2183
|
+
clear() {
|
|
2184
|
+
vfx?.peekWorkshop()?.rain.clear();
|
|
2185
|
+
}
|
|
2186
|
+
};
|
|
2187
|
+
}
|
|
2188
|
+
|
|
2189
|
+
// src/rain-curtain.ts
|
|
2190
|
+
var RAIN_CURTAIN = { count: 14e3, width: 70, height: 25, speed: 13, pointSize: 1.6 };
|
|
2191
|
+
var RAIN_CURTAIN_VERTEX = "uniform float uTime; uniform vec3 uCam; void main(){ vec3 p = position; p.y = mod(p.y - uTime*13., 25.); p.xz = uCam.xz + mod(p.xz - uCam.xz + 35., 70.) - 35.; gl_Position = projectionMatrix*viewMatrix*vec4(p,1.); gl_PointSize = 1.6; }";
|
|
2192
|
+
var RAIN_CURTAIN_FRAGMENT = "uniform float uDay; void main(){ gl_FragColor = vec4(vec3(.68,.72,.78)*(0.25+0.75*uDay), .22+.1*uDay); }";
|
|
2193
|
+
var RAIN_CURTAIN_PROFILES = { low: 0.35, medium: 0.7, high: 1 };
|
|
2194
|
+
var RAIN_CURTAIN_FULL_AT = 4e3;
|
|
2195
|
+
function rainCurtainPositions(random = Math.random, count = RAIN_CURTAIN.count) {
|
|
2196
|
+
const positions = new Float32Array(count * 3);
|
|
2197
|
+
for (let index = 0; index < count; index++) {
|
|
2198
|
+
positions[index * 3] = (random() - 0.5) * RAIN_CURTAIN.width;
|
|
2199
|
+
positions[index * 3 + 1] = random() * RAIN_CURTAIN.height;
|
|
2200
|
+
positions[index * 3 + 2] = (random() - 0.5) * RAIN_CURTAIN.width;
|
|
2201
|
+
}
|
|
2202
|
+
return positions;
|
|
2203
|
+
}
|
|
2204
|
+
function createRainCurtain(THREE, options = {}) {
|
|
2205
|
+
const count = options.count ?? RAIN_CURTAIN.count;
|
|
2206
|
+
const geometry = new THREE.BufferGeometry();
|
|
2207
|
+
geometry.setAttribute("position", new THREE.BufferAttribute(rainCurtainPositions(options.random, count), 3));
|
|
2208
|
+
const uniforms = { uTime: { value: 0 }, uCam: { value: new THREE.Vector3() }, uDay: { value: 1 } };
|
|
2209
|
+
const material = new THREE.ShaderMaterial({ uniforms, transparent: true, depthWrite: false, vertexShader: RAIN_CURTAIN_VERTEX, fragmentShader: RAIN_CURTAIN_FRAGMENT });
|
|
2210
|
+
const object = new THREE.Points(geometry, material);
|
|
2211
|
+
object.frustumCulled = false;
|
|
2212
|
+
object.name = "weather-rain-curtain";
|
|
2213
|
+
object.visible = false;
|
|
2214
|
+
let share = RAIN_CURTAIN_PROFILES[options.profile ?? "high"];
|
|
2215
|
+
let drawn = 0;
|
|
2216
|
+
return {
|
|
2217
|
+
object,
|
|
2218
|
+
update(sample, camera2, time, daylight) {
|
|
2219
|
+
const fullAt = options.fullAt ?? RAIN_CURTAIN_FULL_AT;
|
|
2220
|
+
drawn = sample.rain > 0 ? Math.round(count * share * Math.min(1, sample.drops / fullAt)) : 0;
|
|
2221
|
+
object.visible = drawn > 0;
|
|
2222
|
+
geometry.setDrawRange(0, drawn);
|
|
2223
|
+
uniforms.uTime.value = time;
|
|
2224
|
+
uniforms.uDay.value = daylight;
|
|
2225
|
+
uniforms.uCam.value.set(camera2.x, camera2.y, camera2.z);
|
|
2226
|
+
},
|
|
2227
|
+
setProfile(profile) {
|
|
2228
|
+
share = RAIN_CURTAIN_PROFILES[profile];
|
|
2229
|
+
},
|
|
2230
|
+
drawn: () => drawn,
|
|
2231
|
+
dispose() {
|
|
2232
|
+
geometry.dispose();
|
|
2233
|
+
material.dispose();
|
|
2234
|
+
}
|
|
2235
|
+
};
|
|
2236
|
+
}
|
|
2237
|
+
|
|
2238
|
+
// src/renderer.ts
|
|
2239
|
+
var WEATHER_LAYERS = ["far_rain", "near_rain", "mist", "fog", "sky", "lightning", "headlights", "haze"];
|
|
2240
|
+
function createWeatherRenderer(THREE, options) {
|
|
2241
|
+
const { scene, camera: camera2, weather, vfx } = options;
|
|
2242
|
+
const group = new THREE.Group();
|
|
2243
|
+
group.name = "weather";
|
|
2244
|
+
scene.add(group);
|
|
2245
|
+
const curtain = createRainCurtain(THREE, { ...options.random ? { random: options.random } : {}, ...options.profile ? { profile: options.profile } : {} });
|
|
2246
|
+
const haze = createHeatHaze(THREE);
|
|
2247
|
+
group.add(curtain.object, haze.object);
|
|
2248
|
+
const sky = createSky(THREE, scene);
|
|
2249
|
+
const fog = createFog(THREE, scene);
|
|
2250
|
+
const lightning = createLightning(THREE, scene, vfx);
|
|
2251
|
+
const headlights = createHeadlights(THREE, options.headlights);
|
|
2252
|
+
const nearRain = createNearRain(vfx, { ...options.puddles ? { puddles: options.puddles } : {}, ...options.puddleAt ? { puddleAt: options.puddleAt } : {} });
|
|
2253
|
+
const on = new Map(WEATHER_LAYERS.map((id) => [id, options.layers?.[id] ?? true]));
|
|
2254
|
+
let zone = options.zone;
|
|
2255
|
+
let time = 0;
|
|
2256
|
+
const eye = { x: 0, y: 0, z: 0 };
|
|
2257
|
+
const switchedOff = (id) => {
|
|
2258
|
+
if (id === "far_rain") curtain.object.visible = false;
|
|
2259
|
+
else if (id === "near_rain") nearRain.clear();
|
|
2260
|
+
else if (id === "fog") fog.clear();
|
|
2261
|
+
else if (id === "lightning") lightning.light.intensity = 0;
|
|
2262
|
+
else if (id === "haze") haze.object.visible = false;
|
|
2263
|
+
};
|
|
2264
|
+
return {
|
|
2265
|
+
curtain,
|
|
2266
|
+
nearRain,
|
|
2267
|
+
fog,
|
|
2268
|
+
sky,
|
|
2269
|
+
lightning,
|
|
2270
|
+
headlights,
|
|
2271
|
+
haze,
|
|
2272
|
+
update(dt) {
|
|
2273
|
+
time += dt;
|
|
2274
|
+
const sample = weather.sample();
|
|
2275
|
+
const position = camera2.position;
|
|
2276
|
+
eye.x = position.x;
|
|
2277
|
+
eye.y = position.y;
|
|
2278
|
+
eye.z = position.z;
|
|
2279
|
+
const where = [eye.x, eye.y, eye.z];
|
|
2280
|
+
const background = scene.background ?? void 0;
|
|
2281
|
+
const ownSky = on.get("sky") === true;
|
|
2282
|
+
const color = ownSky ? sky.update(sample, zone) : background && background.isColor ? background : sky.color;
|
|
2283
|
+
if (on.get("fog")) fog.update(sample, color, zone);
|
|
2284
|
+
if (on.get("lightning")) lightning.update(sample, ownSky ? scene.background : void 0);
|
|
2285
|
+
if (on.get("far_rain")) curtain.update(sample, eye, time, sample.sun);
|
|
2286
|
+
if (on.get("haze")) haze.update(sample, time);
|
|
2287
|
+
if (vfx) {
|
|
2288
|
+
if (on.get("near_rain")) nearRain.update(sample, dt, where);
|
|
2289
|
+
if (on.get("mist")) emitAirborne(vfx.workshop(), sample, dt, where);
|
|
2290
|
+
}
|
|
2291
|
+
headlights.update(sample, dt, where, vfx && sample.rain > 0 ? vfx.workshop() : void 0, on.get("headlights"));
|
|
2292
|
+
},
|
|
2293
|
+
setLayer(id, value) {
|
|
2294
|
+
on.set(id, value);
|
|
2295
|
+
if (!value) switchedOff(id);
|
|
2296
|
+
},
|
|
2297
|
+
layer: (id) => on.get(id) === true,
|
|
2298
|
+
setZoneFog(next) {
|
|
2299
|
+
zone = next;
|
|
2300
|
+
},
|
|
2301
|
+
setProfile(profile) {
|
|
2302
|
+
curtain.setProfile(profile);
|
|
2303
|
+
},
|
|
2304
|
+
stats: () => ({ rainCurtain: curtain.drawn(), rainNear: nearRain.count(), cars: headlights.count() }),
|
|
2305
|
+
dispose() {
|
|
2306
|
+
scene.remove(group);
|
|
2307
|
+
curtain.dispose();
|
|
2308
|
+
haze.dispose();
|
|
2309
|
+
lightning.dispose();
|
|
2310
|
+
headlights.dispose();
|
|
2311
|
+
nearRain.clear();
|
|
2312
|
+
}
|
|
2313
|
+
};
|
|
2314
|
+
}
|
|
2315
|
+
|
|
2316
|
+
// src/bench/text.ts
|
|
2317
|
+
var TEXTS = {
|
|
2318
|
+
en: { layers: { far_rain: "Rain curtain", near_rain: "Near rain and splashes", mist: "Mist and ash", sky: "Sky", lightning: "Lightning", headlights: "Headlights", haze: "Heat haze" } },
|
|
2319
|
+
"pt-BR": { layers: { far_rain: "Cortina de chuva", near_rain: "Chuva perto e respingos", mist: "N\xE9voa e cinza", sky: "C\xE9u", lightning: "Rel\xE2mpago", headlights: "Far\xF3is", haze: "N\xE9voa de calor" } }
|
|
2320
|
+
};
|
|
2321
|
+
var weatherVisualTextOf = (locale) => TEXTS[locale] ?? TEXTS[locale.split("-")[0] ?? "en"] ?? TEXTS.en;
|
|
2322
|
+
|
|
2323
|
+
// src/bench/visual.ts
|
|
2324
|
+
var LAYER_ORDER = ["far_rain", "near_rain", "mist", "sky", "lightning", "headlights", "haze"];
|
|
2325
|
+
var RIG_DEFAULT = [1.6, -2.5, 0];
|
|
2326
|
+
function buildRig(THREE) {
|
|
2327
|
+
const group = new THREE.Group();
|
|
2328
|
+
group.name = "weather-lamp-rig";
|
|
2329
|
+
const body = new THREE.Mesh(new THREE.BoxGeometry(1.8, 0.7, 4.2), new THREE.MeshBasicMaterial({ color: 1776928 }));
|
|
2330
|
+
body.position.set(0, 0.5, 0);
|
|
2331
|
+
const lens2 = new THREE.MeshBasicMaterial({ color: HEADLIGHTS.lens.off });
|
|
2332
|
+
const lampGeometry = new THREE.BoxGeometry(0.35, 0.15, 0.05);
|
|
2333
|
+
for (const side of [-1, 1]) {
|
|
2334
|
+
const lamp = new THREE.Mesh(lampGeometry, lens2);
|
|
2335
|
+
lamp.position.set(side * HEADLIGHTS.lamp[0], HEADLIGHTS.lamp[1], 2.11);
|
|
2336
|
+
group.add(lamp);
|
|
2337
|
+
}
|
|
2338
|
+
group.add(body);
|
|
2339
|
+
return {
|
|
2340
|
+
group,
|
|
2341
|
+
lens: lens2,
|
|
2342
|
+
dispose() {
|
|
2343
|
+
body.geometry.dispose();
|
|
2344
|
+
body.material.dispose();
|
|
2345
|
+
lampGeometry.dispose();
|
|
2346
|
+
lens2.dispose();
|
|
2347
|
+
}
|
|
2348
|
+
};
|
|
2349
|
+
}
|
|
2350
|
+
function createWeatherVisual(options = {}) {
|
|
2351
|
+
return {
|
|
2352
|
+
layers(locale) {
|
|
2353
|
+
const text = weatherVisualTextOf(locale);
|
|
2354
|
+
return LAYER_ORDER.map((id) => ({ id, name: text.layers[id], default: options.layers?.[id] ?? true }));
|
|
2355
|
+
},
|
|
2356
|
+
create({ host, weather }) {
|
|
2357
|
+
const THREE = host.THREE;
|
|
2358
|
+
const renderer = createWeatherRenderer(THREE, {
|
|
2359
|
+
scene: host.scene,
|
|
2360
|
+
camera: host.camera,
|
|
2361
|
+
weather,
|
|
2362
|
+
...options.vfx ? { vfx: options.vfx } : {},
|
|
2363
|
+
...options.profile ? { profile: options.profile } : {},
|
|
2364
|
+
...options.random ? { random: options.random } : {},
|
|
2365
|
+
...options.zone ? { zone: options.zone } : {},
|
|
2366
|
+
...options.puddles ? { puddles: options.puddles } : {},
|
|
2367
|
+
...options.puddleAt ? { puddleAt: options.puddleAt } : {},
|
|
2368
|
+
...options.headlights ? { headlights: options.headlights } : {},
|
|
2369
|
+
...options.layers ? { layers: options.layers } : {}
|
|
2370
|
+
});
|
|
2371
|
+
return attachRig(THREE, host, renderer, options.rig === void 0 ? RIG_DEFAULT : options.rig);
|
|
2372
|
+
}
|
|
2373
|
+
};
|
|
2374
|
+
}
|
|
2375
|
+
function attachRig(THREE, host, renderer, place) {
|
|
2376
|
+
const scene = host.scene;
|
|
2377
|
+
const rig = place === false ? void 0 : buildRig(THREE);
|
|
2378
|
+
let detach;
|
|
2379
|
+
if (rig && place) {
|
|
2380
|
+
rig.group.position.set(place[0], 0, place[1]);
|
|
2381
|
+
rig.group.rotation.y = place[2];
|
|
2382
|
+
scene.add(rig.group);
|
|
2383
|
+
detach = renderer.headlights.attach(rig.group, rig.lens);
|
|
2384
|
+
}
|
|
2385
|
+
return {
|
|
2386
|
+
update: (dt) => renderer.update(dt),
|
|
2387
|
+
setLayer(id, on) {
|
|
2388
|
+
if (WEATHER_IDS.includes(id)) renderer.setLayer(id, on);
|
|
2389
|
+
},
|
|
2390
|
+
dispose() {
|
|
2391
|
+
detach?.();
|
|
2392
|
+
if (rig) {
|
|
2393
|
+
scene.remove(rig.group);
|
|
2394
|
+
rig.dispose();
|
|
2395
|
+
}
|
|
2396
|
+
renderer.dispose();
|
|
2397
|
+
}
|
|
2398
|
+
};
|
|
2399
|
+
}
|
|
2400
|
+
var WEATHER_IDS = ["far_rain", "near_rain", "mist", "fog", "sky", "lightning", "headlights", "haze"];
|
|
2401
|
+
return __toCommonJS(index_exports);
|
|
2402
|
+
})();
|
|
2403
|
+
//# sourceMappingURL=index.global.js.map
|