@adatechnology/game-weather 0.1.2 → 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/README.md +36 -2
- package/dist/index.d.ts +181 -2
- package/dist/index.global.js +376 -17
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +210 -17
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
package/dist/index.global.js
CHANGED
|
@@ -23,17 +23,27 @@ var GameWeather = (() => {
|
|
|
23
23
|
__export(index_exports, {
|
|
24
24
|
CLIMATES: () => CLIMATES,
|
|
25
25
|
DAY_REAL_SECONDS: () => DAY_REAL_SECONDS,
|
|
26
|
+
DEFAULT_BRIDGE_RULES: () => DEFAULT_BRIDGE_RULES,
|
|
26
27
|
DEFAULT_DRY_OUT_SECONDS: () => DEFAULT_DRY_OUT_SECONDS,
|
|
28
|
+
DEFAULT_RAIN_SOUND: () => DEFAULT_RAIN_SOUND,
|
|
27
29
|
DEFAULT_START_HOUR: () => DEFAULT_START_HOUR,
|
|
28
30
|
DEFAULT_TIME_SCALE: () => DEFAULT_TIME_SCALE,
|
|
29
31
|
DEFAULT_WET_RISE_SECONDS: () => DEFAULT_WET_RISE_SECONDS,
|
|
32
|
+
DEFAULT_WIND_SOUND: () => DEFAULT_WIND_SOUND,
|
|
30
33
|
DRY_VISIBILITY_METERS: () => DRY_VISIBILITY_METERS,
|
|
31
34
|
FLASH_END_SECONDS: () => FLASH_END_SECONDS,
|
|
32
35
|
GAME_DAY_SECONDS: () => GAME_DAY_SECONDS,
|
|
33
36
|
NIGHT_SIGHT_LOSS: () => NIGHT_SIGHT_LOSS,
|
|
37
|
+
RAIN_HISS_GAME: () => RAIN_HISS_GAME,
|
|
38
|
+
RAIN_LOOP: () => RAIN_LOOP,
|
|
34
39
|
SPEED_OF_SOUND: () => SPEED_OF_SOUND,
|
|
35
40
|
STATE_VALUE_KEYS: () => STATE_VALUE_KEYS,
|
|
41
|
+
THUNDER: () => THUNDER,
|
|
42
|
+
WEATHER_BANK: () => WEATHER_BANK,
|
|
43
|
+
WEATHER_LOOPS: () => WEATHER_LOOPS,
|
|
44
|
+
WEATHER_SOUNDS: () => WEATHER_SOUNDS,
|
|
36
45
|
WEATHER_STATES: () => WEATHER_STATES,
|
|
46
|
+
WIND_LOOP: () => WIND_LOOP,
|
|
37
47
|
blendValues: () => blendValues,
|
|
38
48
|
createLightningStream: () => createLightningStream,
|
|
39
49
|
createRng: () => createRng,
|
|
@@ -41,19 +51,25 @@ var GameWeather = (() => {
|
|
|
41
51
|
createStream: () => createStream,
|
|
42
52
|
createTimeline: () => createTimeline,
|
|
43
53
|
createWeather: () => createWeather,
|
|
54
|
+
createWeatherBridges: () => createWeatherBridges,
|
|
44
55
|
createWeatherRegistry: () => createWeatherRegistry,
|
|
56
|
+
createWeatherSound: () => createWeatherSound,
|
|
45
57
|
createWeatherTestModule: () => createWeatherTestModule,
|
|
46
58
|
createWetness: () => createWetness,
|
|
47
59
|
dayFractionAt: () => dayFractionAt,
|
|
48
60
|
daylight: () => daylight,
|
|
49
61
|
deriveEffects: () => deriveEffects,
|
|
62
|
+
environmentOf: () => environmentOf,
|
|
50
63
|
flashIntensity: () => flashIntensity,
|
|
51
64
|
heatIndexC: () => heatIndexC,
|
|
52
65
|
heatStress: () => heatStress,
|
|
66
|
+
rainVolume: () => rainVolume,
|
|
53
67
|
streamSeed: () => streamSeed,
|
|
68
|
+
strikePosition: () => strikePosition,
|
|
54
69
|
thunderDelay: () => thunderDelay,
|
|
55
70
|
valuesOf: () => valuesOf,
|
|
56
|
-
weatherBenchTextOf: () => weatherBenchTextOf
|
|
71
|
+
weatherBenchTextOf: () => weatherBenchTextOf,
|
|
72
|
+
windVolume: () => windVolume
|
|
57
73
|
});
|
|
58
74
|
|
|
59
75
|
// src/blend.ts
|
|
@@ -829,6 +845,343 @@ var GameWeather = (() => {
|
|
|
829
845
|
};
|
|
830
846
|
}
|
|
831
847
|
|
|
848
|
+
// ../game-audio/dist/index.js
|
|
849
|
+
var DISTANCE_CURVES = {
|
|
850
|
+
/** The game's `sfx`: `vol / (1 + d² × 0.004)`, cutoff `/ (1 + d × 0.01)`, silent below 0.01 (jogo L62091–62092, L62101). */
|
|
851
|
+
game_sfx: { model: "inverse_square", k: 4e-3, cutoffK: 0.01, minGain: 0.01 },
|
|
852
|
+
/** The game's `grito`: `1 / (1 + d² × 0.006)`, silent below 0.02 (jogo L62129–62130). */
|
|
853
|
+
game_scream: { model: "inverse_square", k: 6e-3, minGain: 0.02 },
|
|
854
|
+
/** The game's `voz`: `1 / (1 + d² × 0.01)`, silent below 0.02 (jogo L62146–62147). */
|
|
855
|
+
game_voice: { model: "inverse_square", k: 0.01, minGain: 0.02 },
|
|
856
|
+
/** The game's `boom`: `1.4 / (1 + d² × 0.002)`, never silent (jogo L68280). */
|
|
857
|
+
game_boom: { model: "inverse_square", k: 2e-3, scale: 1.4 },
|
|
858
|
+
/** The art scene's `outAt`: `vol / (1 + d² × 0.008)` (cena L1320). */
|
|
859
|
+
art_scene: { model: "inverse_square", k: 8e-3 },
|
|
860
|
+
/** The game's animal calls: `max(0, 1 − d / 70) × 0.25`, silent at or below 0.005 (jogo L66627–66628). */
|
|
861
|
+
animals: { model: "linear", range: 70, scale: 0.25, minGain: 5e-3 }
|
|
862
|
+
};
|
|
863
|
+
var mix_profiles_default = [
|
|
864
|
+
{
|
|
865
|
+
id: "game",
|
|
866
|
+
master: 0.5,
|
|
867
|
+
noise: { seconds: 1.5, create: "lazy" },
|
|
868
|
+
sources: ["jogo:L62077-62081 master 0.5 to the output", "jogo:L62082-62088 noise 1.5 s made by the first sound that needs it"]
|
|
869
|
+
},
|
|
870
|
+
{
|
|
871
|
+
id: "art_scene",
|
|
872
|
+
master: 0.85,
|
|
873
|
+
compressor: { threshold: -12, ratio: 5 },
|
|
874
|
+
reverb: { seconds: 2.2, decay: 3.4, wet: 0.4 },
|
|
875
|
+
noise: { seconds: 2, create: "eager" },
|
|
876
|
+
sources: [
|
|
877
|
+
"cena:L1308 compressor -12 dB, ratio 5",
|
|
878
|
+
"cena:L1309 master 0.85",
|
|
879
|
+
"cena:L1310 convolver, impulse 2.2 s of (1 - i/len)^3.4",
|
|
880
|
+
"cena:L1311 wet 0.4",
|
|
881
|
+
"cena:L1312 noise 2 s made with the chain"
|
|
882
|
+
]
|
|
883
|
+
}
|
|
884
|
+
];
|
|
885
|
+
var MIX_PROFILES = Object.fromEntries(
|
|
886
|
+
mix_profiles_default.map((profile) => [profile.id, profile])
|
|
887
|
+
);
|
|
888
|
+
var game_sfx_default = {
|
|
889
|
+
sources: ["jogo:L62089-62107"],
|
|
890
|
+
note: "The game's sfx table P: [lowpass cutoff Hz, peak gain, seconds]. Played as a noise burst with the game's distance curve (falloff game_sfx) and a 0.05 s tail. Team names in `team`.",
|
|
891
|
+
classes: [
|
|
892
|
+
{ id: "pistol", team: "pistola", bus: "weapons", cutoff: 1800, gain: 0.9, seconds: 0.18 },
|
|
893
|
+
{ id: "shotgun", team: "escopeta", bus: "weapons", cutoff: 900, gain: 1.2, seconds: 0.35 },
|
|
894
|
+
{ id: "rifle", team: "fuzil", bus: "weapons", cutoff: 1400, gain: 1.1, seconds: 0.28 },
|
|
895
|
+
{ id: "long_rifle", team: "rifle", bus: "weapons", cutoff: 1100, gain: 1.3, seconds: 0.45 },
|
|
896
|
+
{ id: "impact", team: "impacto", bus: "world", cutoff: 2500, gain: 0.25, seconds: 0.05 },
|
|
897
|
+
{ id: "flesh", team: "carne", bus: "world", cutoff: 600, gain: 0.35, seconds: 0.08 },
|
|
898
|
+
{ id: "step", team: "passo", bus: "world", cutoff: 400, gain: 0.08, seconds: 0.05 },
|
|
899
|
+
{ id: "glass", team: "vidro", bus: "world", cutoff: 5e3, gain: 0.5, seconds: 0.3 },
|
|
900
|
+
{ id: "wood", team: "madeira", bus: "world", cutoff: 700, gain: 0.5, seconds: 0.2 },
|
|
901
|
+
{ id: "reload", team: "recarga", bus: "weapons", cutoff: 3e3, gain: 0.15, seconds: 0.06 },
|
|
902
|
+
{ id: "empty", team: "vazio", bus: "weapons", cutoff: 4e3, gain: 0.12, seconds: 0.03 },
|
|
903
|
+
{ id: "explosion", team: "explosao", bus: "world", cutoff: 200, gain: 1.6, seconds: 1.4 }
|
|
904
|
+
],
|
|
905
|
+
fallback: { id: "unknown", team: "(any other name)", bus: "world", cutoff: 1e3, gain: 0.5, seconds: 0.1 }
|
|
906
|
+
};
|
|
907
|
+
var GAME_SFX = game_sfx_default;
|
|
908
|
+
var GAME_SFX_CLASSES = GAME_SFX.classes;
|
|
909
|
+
var GAME_SFX_FALLBACK = GAME_SFX.fallback;
|
|
910
|
+
function noiseClassRecipe(row, id = `sfx_${row.id}`) {
|
|
911
|
+
return {
|
|
912
|
+
id,
|
|
913
|
+
bus: row.bus,
|
|
914
|
+
order: "burst",
|
|
915
|
+
duration: row.seconds,
|
|
916
|
+
tail: 0.05,
|
|
917
|
+
layers: [
|
|
918
|
+
{
|
|
919
|
+
source: { kind: "noise", offset: "random" },
|
|
920
|
+
filters: { mode: "serial", bank: [{ type: "lowpass", frequency: { set: row.cutoff } }] },
|
|
921
|
+
envelope: [
|
|
922
|
+
[0, row.gain, "set"],
|
|
923
|
+
["1d", 1e-3, "exp", "fixed"]
|
|
924
|
+
]
|
|
925
|
+
}
|
|
926
|
+
],
|
|
927
|
+
falloff: DISTANCE_CURVES.game_sfx,
|
|
928
|
+
sources: [...GAME_SFX.sources.map((source) => `${source} ${row.team}`)]
|
|
929
|
+
};
|
|
930
|
+
}
|
|
931
|
+
var GAME_SFX_BANK = { id: "game_sfx", sounds: [...GAME_SFX_CLASSES, GAME_SFX_FALLBACK].map((row) => noiseClassRecipe(row)) };
|
|
932
|
+
var ATTACK = 2e-3;
|
|
933
|
+
function lengthOf(d, attack) {
|
|
934
|
+
if (typeof d === "number") return attack + d;
|
|
935
|
+
if (Array.isArray(d)) return [attack + d[0], attack + d[1]];
|
|
936
|
+
return { ...d, add: (d.add ?? 0) + attack };
|
|
937
|
+
}
|
|
938
|
+
var envelope = (attack) => [
|
|
939
|
+
[0, 1e-4, "set", "fixed"],
|
|
940
|
+
[attack, 1, "exp"],
|
|
941
|
+
["1d", 1e-4, "exp", "fixed"]
|
|
942
|
+
];
|
|
943
|
+
function sceneNoise(o) {
|
|
944
|
+
const a = o.a ?? ATTACK;
|
|
945
|
+
const over = typeof o.d === "number" ? o.d : 0;
|
|
946
|
+
return {
|
|
947
|
+
filters: {
|
|
948
|
+
mode: "serial",
|
|
949
|
+
bank: [{ type: o.type ?? "lowpass", frequency: o.f2 === void 0 ? { set: o.f } : { set: o.f, to: o.f2, curve: "exp", over }, q: o.q ?? 0.7 }]
|
|
950
|
+
},
|
|
951
|
+
duration: lengthOf(o.d, a),
|
|
952
|
+
gain: o.vol,
|
|
953
|
+
...o.delay === void 0 ? {} : { at: o.delay },
|
|
954
|
+
...o.wet === void 0 ? {} : { wet: o.wet },
|
|
955
|
+
source: { kind: "noise", offset: "random", offsetScale: 1.5, loop: true },
|
|
956
|
+
envelope: envelope(a)
|
|
957
|
+
};
|
|
958
|
+
}
|
|
959
|
+
function sceneTone(o) {
|
|
960
|
+
return {
|
|
961
|
+
source: { kind: "osc", wave: o.wave ?? "sine", frequency: { from: o.f, to: o.f2 ?? "from", curve: "exp", over: "duration" } },
|
|
962
|
+
duration: lengthOf(o.d, ATTACK),
|
|
963
|
+
gain: o.vol,
|
|
964
|
+
...o.delay === void 0 ? {} : { at: o.delay },
|
|
965
|
+
...o.wet === void 0 ? {} : { wet: o.wet },
|
|
966
|
+
envelope: envelope(ATTACK)
|
|
967
|
+
};
|
|
968
|
+
}
|
|
969
|
+
var BENCH_BANK = {
|
|
970
|
+
id: "audio_bench",
|
|
971
|
+
sounds: [
|
|
972
|
+
{
|
|
973
|
+
id: "bench_ping",
|
|
974
|
+
bus: "ui",
|
|
975
|
+
pan: true,
|
|
976
|
+
duration: 0.25,
|
|
977
|
+
layers: [
|
|
978
|
+
{
|
|
979
|
+
gain: 0.5,
|
|
980
|
+
wet: 0.3,
|
|
981
|
+
source: { kind: "osc", wave: "sine", frequency: { from: 880 } },
|
|
982
|
+
envelope: [
|
|
983
|
+
[0, 1e-4, "set", "fixed"],
|
|
984
|
+
[2e-3, 1, "exp"],
|
|
985
|
+
["1d", 1e-4, "exp", "fixed"]
|
|
986
|
+
]
|
|
987
|
+
}
|
|
988
|
+
],
|
|
989
|
+
falloff: DISTANCE_CURVES.art_scene,
|
|
990
|
+
sources: ["sdk: bench probe, a 880 Hz ping through the art scene output stage"]
|
|
991
|
+
},
|
|
992
|
+
{
|
|
993
|
+
id: "bench_hiss",
|
|
994
|
+
bus: "ui",
|
|
995
|
+
pan: true,
|
|
996
|
+
duration: [0.3, 0.9],
|
|
997
|
+
layers: [
|
|
998
|
+
{
|
|
999
|
+
gain: 0.4,
|
|
1000
|
+
source: { kind: "noise", offset: "random", offsetScale: 1.5, loop: true },
|
|
1001
|
+
filters: { mode: "serial", bank: [{ type: "highpass", frequency: { set: 3e3 }, q: 0.7 }] },
|
|
1002
|
+
envelope: [
|
|
1003
|
+
[0, 1e-4, "set", "fixed"],
|
|
1004
|
+
[2e-3, 1, "exp"],
|
|
1005
|
+
["1d", 1e-4, "exp", "fixed"]
|
|
1006
|
+
]
|
|
1007
|
+
}
|
|
1008
|
+
],
|
|
1009
|
+
falloff: DISTANCE_CURVES.art_scene,
|
|
1010
|
+
sources: ["sdk: bench probe, a highpass hiss of random length"]
|
|
1011
|
+
}
|
|
1012
|
+
]
|
|
1013
|
+
};
|
|
1014
|
+
|
|
1015
|
+
// src/audio/recipes.ts
|
|
1016
|
+
var RAIN_LOOP = {
|
|
1017
|
+
id: "rain_loop",
|
|
1018
|
+
bus: "weather",
|
|
1019
|
+
order: "chain_loop",
|
|
1020
|
+
source: { kind: "noise", loop: true },
|
|
1021
|
+
filters: {
|
|
1022
|
+
mode: "serial",
|
|
1023
|
+
bank: [
|
|
1024
|
+
{ type: "highpass", frequency: { set: 600 } },
|
|
1025
|
+
{ type: "lowpass", frequency: { set: 6e3 } }
|
|
1026
|
+
]
|
|
1027
|
+
},
|
|
1028
|
+
sources: ["cena:L1314"]
|
|
1029
|
+
};
|
|
1030
|
+
var WIND_LOOP = {
|
|
1031
|
+
id: "wind_loop",
|
|
1032
|
+
bus: "weather",
|
|
1033
|
+
order: "chain_loop",
|
|
1034
|
+
source: { kind: "noise", loop: true },
|
|
1035
|
+
filters: { mode: "serial", bank: [{ type: "lowpass", frequency: { set: 320 } }] },
|
|
1036
|
+
modulators: [{ target: "gain", rate: 0.07, depth: 0.035 }],
|
|
1037
|
+
sources: ["cena:L1315"]
|
|
1038
|
+
};
|
|
1039
|
+
var RAIN_HISS_GAME = {
|
|
1040
|
+
id: "rain_hiss_game",
|
|
1041
|
+
bus: "weather",
|
|
1042
|
+
order: "game_loop",
|
|
1043
|
+
source: { kind: "noise", loop: true },
|
|
1044
|
+
filters: { mode: "serial", bank: [{ type: "highpass", frequency: { set: 2500 } }] },
|
|
1045
|
+
sources: ["jogo:L62116 chuva"]
|
|
1046
|
+
};
|
|
1047
|
+
var THUNDER = {
|
|
1048
|
+
id: "thunder",
|
|
1049
|
+
bus: "weather",
|
|
1050
|
+
pan: true,
|
|
1051
|
+
layers: [sceneTone({ f: 70, f2: 28, d: 1.2, vol: 1 }), sceneNoise({ f: 260, f2: 50, d: 3.2, vol: 0.9, wet: 0.8 })],
|
|
1052
|
+
falloff: { model: "inverse_square", k: 1e-5, scale: 1.4 },
|
|
1053
|
+
sources: ["jogo:L68278-68285 boom", "sdk: rumble and falloff"]
|
|
1054
|
+
};
|
|
1055
|
+
var WEATHER_BANK = { id: "weather", sounds: [THUNDER], loops: [RAIN_LOOP, WIND_LOOP, RAIN_HISS_GAME] };
|
|
1056
|
+
var WEATHER_SOUNDS = WEATHER_BANK.sounds ?? [];
|
|
1057
|
+
var WEATHER_LOOPS = WEATHER_BANK.loops ?? [];
|
|
1058
|
+
|
|
1059
|
+
// src/audio/sound.ts
|
|
1060
|
+
var DEFAULT_RAIN_SOUND = { light: 0.035, heavy: 0.06, lightAt: 2.5, heavyAt: 15 };
|
|
1061
|
+
var DEFAULT_WIND_SOUND = { base: 0.05, referenceSpeed: 3.8, max: 0.12 };
|
|
1062
|
+
function rainVolume(rain, options = {}) {
|
|
1063
|
+
if (!(rain > 0)) return 0;
|
|
1064
|
+
const { light, heavy, lightAt, heavyAt } = { ...DEFAULT_RAIN_SOUND, ...options };
|
|
1065
|
+
if (heavyAt <= lightAt) return rain >= heavyAt ? heavy : light;
|
|
1066
|
+
const t = Math.min(1, Math.max(0, (rain - lightAt) / (heavyAt - lightAt)));
|
|
1067
|
+
return light + (heavy - light) * t;
|
|
1068
|
+
}
|
|
1069
|
+
function windVolume(speed, options = {}) {
|
|
1070
|
+
const { base, referenceSpeed, max } = { ...DEFAULT_WIND_SOUND, ...options };
|
|
1071
|
+
return Math.min(max, base * Math.max(0, speed) / referenceSpeed);
|
|
1072
|
+
}
|
|
1073
|
+
function strikePosition(strike, origin = [0, 0, 0]) {
|
|
1074
|
+
const angle = strike.bearing * Math.PI / 180;
|
|
1075
|
+
return [origin[0] + Math.sin(angle) * strike.distance, origin[1], origin[2] - Math.cos(angle) * strike.distance];
|
|
1076
|
+
}
|
|
1077
|
+
function createWeatherSound(sink, options = {}) {
|
|
1078
|
+
if (sink && options.register !== false) sink.register?.(WEATHER_BANK);
|
|
1079
|
+
const rainSound = options.style === "game" ? "rain_hiss_game" : "rain_loop";
|
|
1080
|
+
const loops = /* @__PURE__ */ new Map();
|
|
1081
|
+
const set = (id, volume) => {
|
|
1082
|
+
let loop = loops.get(id);
|
|
1083
|
+
if (!loop) {
|
|
1084
|
+
if (!(volume > 0) || !sink?.loop) return;
|
|
1085
|
+
loop = sink.loop(id);
|
|
1086
|
+
loops.set(id, loop);
|
|
1087
|
+
}
|
|
1088
|
+
loop.set({ volume });
|
|
1089
|
+
};
|
|
1090
|
+
return {
|
|
1091
|
+
update(sample) {
|
|
1092
|
+
set(rainSound, rainVolume(sample.rain, options.rain));
|
|
1093
|
+
set("wind_loop", windVolume(sample.windSpeed, options.wind));
|
|
1094
|
+
},
|
|
1095
|
+
thunder(strike) {
|
|
1096
|
+
sink?.play({ sound: "thunder", position: strikePosition(strike, options.listener?.()), ...options.thunderVolume === void 0 ? {} : { volume: options.thunderVolume } });
|
|
1097
|
+
},
|
|
1098
|
+
dispose() {
|
|
1099
|
+
for (const loop of loops.values()) loop.stop();
|
|
1100
|
+
loops.clear();
|
|
1101
|
+
}
|
|
1102
|
+
};
|
|
1103
|
+
}
|
|
1104
|
+
|
|
1105
|
+
// src/bridges.ts
|
|
1106
|
+
var DEFAULT_BRIDGE_RULES = { filmRainFullAt: 2.5, washFrom: 15, washBelow: 0.5, washEvery: 1, windFull: 20 };
|
|
1107
|
+
function environmentOf(sample) {
|
|
1108
|
+
return {
|
|
1109
|
+
rain: sample.rain,
|
|
1110
|
+
windX: sample.windX,
|
|
1111
|
+
windZ: sample.windZ,
|
|
1112
|
+
windSpeed: sample.windSpeed,
|
|
1113
|
+
gust: sample.gust,
|
|
1114
|
+
fogFar: sample.fogFar,
|
|
1115
|
+
visibility: sample.effects.visibility,
|
|
1116
|
+
nightFactor: sample.nightFactor,
|
|
1117
|
+
temperatureC: sample.temperatureC,
|
|
1118
|
+
wetness: sample.groundWetness
|
|
1119
|
+
};
|
|
1120
|
+
}
|
|
1121
|
+
function createWeatherBridges(targets, options = {}) {
|
|
1122
|
+
const rules = { ...DEFAULT_BRIDGE_RULES, ...options };
|
|
1123
|
+
const sound = options.sound === false || !targets.audio ? void 0 : createWeatherSound(targets.audio, options.sound ?? {});
|
|
1124
|
+
let weather;
|
|
1125
|
+
let offThunder;
|
|
1126
|
+
let sinceWash = 0;
|
|
1127
|
+
let last = {};
|
|
1128
|
+
const push = () => {
|
|
1129
|
+
if (!weather) return;
|
|
1130
|
+
const sample = weather.sample();
|
|
1131
|
+
const { film, interactables, vegetation, vfx, environment } = targets;
|
|
1132
|
+
environment?.set(environmentOf(sample));
|
|
1133
|
+
if (film) {
|
|
1134
|
+
const rain = Math.min(1, Math.max(0, sample.rain / rules.filmRainFullAt));
|
|
1135
|
+
const drying = sample.effects.dryingScale;
|
|
1136
|
+
if (rain !== last.filmRain || drying !== last.drying) film.setWeather({ rain, drying });
|
|
1137
|
+
last.filmRain = rain;
|
|
1138
|
+
last.drying = drying;
|
|
1139
|
+
}
|
|
1140
|
+
if (interactables && sample.rain !== last.rain) interactables.water.setRain(sample.rain);
|
|
1141
|
+
const windChanged = sample.windX !== last.windX || sample.windZ !== last.windZ;
|
|
1142
|
+
if (windChanged) {
|
|
1143
|
+
interactables?.setWind(sample.windX, sample.windZ);
|
|
1144
|
+
vfx?.setWind([sample.windX, 0, sample.windZ]);
|
|
1145
|
+
if (vegetation) {
|
|
1146
|
+
const wind = { strength: Math.min(1, sample.windSpeed / rules.windFull), gust: Math.min(1, sample.gust / rules.windFull) };
|
|
1147
|
+
vegetation.setWind(sample.windSpeed > 1e-6 ? { direction: [sample.windX, sample.windZ], ...wind } : wind);
|
|
1148
|
+
}
|
|
1149
|
+
}
|
|
1150
|
+
last = { ...last, rain: sample.rain, windX: sample.windX, windZ: sample.windZ };
|
|
1151
|
+
sound?.update(sample);
|
|
1152
|
+
};
|
|
1153
|
+
const onThunder = (strike) => sound?.thunder(strike);
|
|
1154
|
+
return {
|
|
1155
|
+
bind(next) {
|
|
1156
|
+
offThunder?.();
|
|
1157
|
+
weather = next;
|
|
1158
|
+
offThunder = next.on("thunder", onThunder);
|
|
1159
|
+
last = {};
|
|
1160
|
+
sinceWash = 0;
|
|
1161
|
+
push();
|
|
1162
|
+
},
|
|
1163
|
+
update(dt) {
|
|
1164
|
+
push();
|
|
1165
|
+
if (!weather || !targets.film?.wash) return;
|
|
1166
|
+
if (weather.sample().rain < rules.washFrom) {
|
|
1167
|
+
sinceWash = 0;
|
|
1168
|
+
return;
|
|
1169
|
+
}
|
|
1170
|
+
sinceWash += dt;
|
|
1171
|
+
if (sinceWash >= rules.washEvery) {
|
|
1172
|
+
sinceWash = 0;
|
|
1173
|
+
targets.film.wash(rules.washBelow);
|
|
1174
|
+
}
|
|
1175
|
+
},
|
|
1176
|
+
dispose() {
|
|
1177
|
+
offThunder?.();
|
|
1178
|
+
offThunder = void 0;
|
|
1179
|
+
weather = void 0;
|
|
1180
|
+
sound?.dispose();
|
|
1181
|
+
}
|
|
1182
|
+
};
|
|
1183
|
+
}
|
|
1184
|
+
|
|
832
1185
|
// src/bench/locale.ts
|
|
833
1186
|
var EN = {
|
|
834
1187
|
group: "Weather",
|
|
@@ -931,9 +1284,12 @@ var GameWeather = (() => {
|
|
|
931
1284
|
function createWeatherTestModule(options = {}) {
|
|
932
1285
|
const locale = options.locale ?? "pt-BR";
|
|
933
1286
|
const text = weatherBenchTextOf(locale);
|
|
934
|
-
const { locale: _locale, translate, weather: given, fog: _fog, ...weatherOptions } = options;
|
|
1287
|
+
const { locale: _locale, translate, weather: given, fog: _fog, targets: _targets, sound: _sound, visual: _visual, ...weatherOptions } = options;
|
|
935
1288
|
void _locale;
|
|
936
1289
|
void _fog;
|
|
1290
|
+
void _targets;
|
|
1291
|
+
void _sound;
|
|
1292
|
+
void _visual;
|
|
937
1293
|
const state = {
|
|
938
1294
|
seed: options.seed ?? 1,
|
|
939
1295
|
hour: options.startHour ?? 8,
|
|
@@ -945,6 +1301,8 @@ var GameWeather = (() => {
|
|
|
945
1301
|
let host = null;
|
|
946
1302
|
let strikes = 0;
|
|
947
1303
|
let offStrike;
|
|
1304
|
+
let bridges;
|
|
1305
|
+
let visual;
|
|
948
1306
|
let weather = given ?? createWeather({ ...weatherOptions, autoSchedule: state.auto, ...state.auto ? { timeScale: FAST_SCALE } : {} });
|
|
949
1307
|
const watch = () => {
|
|
950
1308
|
offStrike?.();
|
|
@@ -957,19 +1315,8 @@ var GameWeather = (() => {
|
|
|
957
1315
|
weather = createWeather({ ...weatherOptions, seed: state.seed, start: current, startHour: state.hour, autoSchedule: state.auto, timeScale: state.auto ? FAST_SCALE : NORMAL_SCALE });
|
|
958
1316
|
strikes = 0;
|
|
959
1317
|
watch();
|
|
1318
|
+
bridges?.bind(weather);
|
|
960
1319
|
};
|
|
961
|
-
const toEnvironment = (sample) => ({
|
|
962
|
-
rain: sample.rain,
|
|
963
|
-
windX: sample.windX,
|
|
964
|
-
windZ: sample.windZ,
|
|
965
|
-
windSpeed: sample.windSpeed,
|
|
966
|
-
gust: sample.gust,
|
|
967
|
-
fogFar: sample.fogFar,
|
|
968
|
-
visibility: sample.effects.visibility,
|
|
969
|
-
nightFactor: sample.nightFactor,
|
|
970
|
-
temperatureC: sample.temperatureC,
|
|
971
|
-
wetness: sample.groundWetness
|
|
972
|
-
});
|
|
973
1320
|
const applyFog = (far) => {
|
|
974
1321
|
const scene = host?.scene;
|
|
975
1322
|
const Fog = host?.THREE?.Fog;
|
|
@@ -980,12 +1327,13 @@ var GameWeather = (() => {
|
|
|
980
1327
|
};
|
|
981
1328
|
const publish = () => {
|
|
982
1329
|
const sample = weather.sample();
|
|
983
|
-
if (state.environment) host?.environment?.set(
|
|
984
|
-
if (state.fog) applyFog(sample.fogFar);
|
|
1330
|
+
if (state.environment) host?.environment?.set(environmentOf(sample));
|
|
1331
|
+
if (state.fog && !visual) applyFog(sample.fogFar);
|
|
985
1332
|
};
|
|
986
1333
|
const onChange = (change) => {
|
|
987
1334
|
if (change.kind === "layer") {
|
|
988
1335
|
if (change.id === "environment" || change.id === "fog") state[change.id] = change.on;
|
|
1336
|
+
visual?.setLayer(change.id, change.on);
|
|
989
1337
|
return;
|
|
990
1338
|
}
|
|
991
1339
|
if (change.kind === "action") return;
|
|
@@ -1023,7 +1371,8 @@ var GameWeather = (() => {
|
|
|
1023
1371
|
];
|
|
1024
1372
|
const layers = () => [
|
|
1025
1373
|
{ id: "environment", name: text.layers.environment },
|
|
1026
|
-
{ id: "fog", name: text.layers.fog, default: state.fog }
|
|
1374
|
+
{ id: "fog", name: text.layers.fog, default: state.fog },
|
|
1375
|
+
...options.visual?.layers(locale) ?? []
|
|
1027
1376
|
];
|
|
1028
1377
|
const metrics = () => [
|
|
1029
1378
|
{ id: "current_state", name: text.metrics.state, read: () => nameOf(weather.state()) },
|
|
@@ -1112,14 +1461,24 @@ var GameWeather = (() => {
|
|
|
1112
1461
|
attach(lent) {
|
|
1113
1462
|
host = lent;
|
|
1114
1463
|
const off = lent.bench?.onChange(onChange);
|
|
1464
|
+
bridges = createWeatherBridges({ ...options.targets, ...lent.audio ? { audio: lent.audio } : {} }, { sound: options.sound ?? {} });
|
|
1465
|
+
bridges.bind(weather);
|
|
1466
|
+
visual = options.visual?.create({ host: lent, locale, weather: { sample: () => weather.sample() } });
|
|
1467
|
+
if (visual && !state.fog) visual.setLayer("fog", false);
|
|
1115
1468
|
publish();
|
|
1116
1469
|
const offFrame = lent.onFrame((dt) => {
|
|
1117
1470
|
weather.advance(dt);
|
|
1118
1471
|
publish();
|
|
1472
|
+
bridges?.update(dt);
|
|
1473
|
+
visual?.update(dt);
|
|
1119
1474
|
});
|
|
1120
1475
|
return () => {
|
|
1476
|
+
visual?.dispose();
|
|
1477
|
+
visual = void 0;
|
|
1121
1478
|
off?.();
|
|
1122
1479
|
offFrame();
|
|
1480
|
+
bridges?.dispose();
|
|
1481
|
+
bridges = void 0;
|
|
1123
1482
|
host = null;
|
|
1124
1483
|
};
|
|
1125
1484
|
}
|