tarinai/js/weather_system.js

86 lines
2.9 KiB
JavaScript
Raw Normal View History

2026-06-21 22:29:00 +09:00
"use strict";
(function (global) {
2026-06-29 16:21:58 +09:00
function chooseNext(current = "sunny") {
const choices = current === "light_rain"
? ["sunny", "cloudy"]
: ["sunny", "cloudy", "light_rain"];
return pick(choices);
}
2026-06-21 22:29:00 +09:00
2026-06-29 16:21:58 +09:00
function resetTimer() {
return rand(CONFIG.weatherChangeMin, CONFIG.weatherChangeMax);
}
2026-06-21 22:29:00 +09:00
2026-06-29 16:21:58 +09:00
function fixedWeatherFor(worldRef) {
const fixed = global.TarinaiGround.fixedWeather(worldRef?.groundType || "soil") || "";
return fixed || null;
}
2026-06-21 22:29:00 +09:00
2026-06-29 16:21:58 +09:00
function enforceFixedWeather(worldRef) {
const fixed = fixedWeatherFor(worldRef);
if (!fixed || !worldRef) return false;
const previous = worldRef.weather || "sunny";
worldRef.weather = fixed;
worldRef.nextWeatherChange = resetTimer();
if (previous !== fixed) {
worldRef.emit?.("weather:changed", { previous, next: fixed });
2026-06-30 22:30:37 +09:00
worldRef.log?.(`\u5929\u6C17: ${weatherLabel(fixed)}`);
2026-06-29 16:21:58 +09:00
}
return true;
}
2026-06-21 22:29:00 +09:00
2026-06-29 16:21:58 +09:00
function shouldDropRainWater(worldRef, dt = 0) {
return Boolean(
worldRef?.weather === "light_rain" &&
Math.random() < Math.max(0, Number(dt) || 0) * 0.12
);
}
2026-06-26 19:04:32 +09:00
2026-07-03 20:57:02 +09:00
function createRainWaterItem(worldRef, opts = {}) {
const px = Number(opts?.x);
const py = Number(opts?.y);
const hasX = Number.isFinite(px);
const hasY = Number.isFinite(py);
const x = hasX ? px : rand(58, worldRef.w - 58);
const y = hasY ? py : rand(58, worldRef.h - 58);
const drop = new Item("water", x, y);
const amount = Number(opts?.amount);
drop.amount = Number.isFinite(amount) ? amount : rand(24, 58);
// Rain drops, placed water drops, and water-balloon splashes all use the
// same Item("water") object. Optional velocity only gives that same water
// item a short ballistic motion; it is not a separate splash item type.
const vx = Number(opts?.vx);
const vy = Number(opts?.vy);
if (Number.isFinite(vx) || Number.isFinite(vy)) {
drop.prevX = drop.x;
drop.prevY = drop.y;
drop.vx = Number.isFinite(vx) ? vx : 0;
drop.vy = Number.isFinite(vy) ? vy : 0;
}
const flight = Number(opts?.splashFlightTimer ?? opts?.flightTimer);
if (Number.isFinite(flight) && flight > 0) drop.splashFlightTimer = flight;
2026-06-29 16:21:58 +09:00
return drop;
}
2026-06-26 19:04:32 +09:00
2026-06-29 16:21:58 +09:00
function applyNextWeather(worldRef) {
if (!worldRef) return null;
if (enforceFixedWeather(worldRef)) return worldRef.weather || "sunny";
const previous = worldRef.weather || "sunny";
const next = chooseNext(previous);
worldRef.weather = next;
worldRef.nextWeatherChange = resetTimer();
if (next !== previous) {
worldRef.emit?.("weather:changed", { previous, next });
2026-06-30 22:30:37 +09:00
worldRef.log?.(`\u5929\u6C17: ${weatherLabel(next)}`);
2026-06-29 16:21:58 +09:00
}
return next;
}
2026-06-21 22:29:00 +09:00
2026-06-29 16:21:58 +09:00
global.TarinaiWeatherSystem = Object.freeze({
enforceFixedWeather,
shouldDropRainWater,
createRainWaterItem,
applyNextWeather,
2026-06-21 22:29:00 +09:00
});
})(typeof window !== "undefined" ? window : globalThis);