2026-06-21 22:29:00 +09:00
|
|
|
"use strict";
|
|
|
|
|
|
|
|
|
|
(function (global) {
|
2026-07-05 18:01:36 +09:00
|
|
|
const DomainIds = global.TarinaiDomainIds;
|
|
|
|
|
if (!DomainIds) throw new Error("TarinaiDomainIds must be loaded before weather_system.js");
|
|
|
|
|
const WEATHER_IDS = DomainIds.WEATHER_IDS;
|
|
|
|
|
function canonicalWeather(value = "sunny") {
|
|
|
|
|
return DomainIds.canonicalWeatherId(value);
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-29 16:21:58 +09:00
|
|
|
function chooseNext(current = "sunny") {
|
2026-07-05 18:01:36 +09:00
|
|
|
const id = canonicalWeather(current);
|
|
|
|
|
const choices = id === "light_rain"
|
|
|
|
|
? WEATHER_IDS.filter(weather => weather !== "light_rain")
|
|
|
|
|
: WEATHER_IDS;
|
2026-06-29 16:21:58 +09:00
|
|
|
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;
|
2026-07-05 18:01:36 +09:00
|
|
|
const previous = canonicalWeather(worldRef.weather || "sunny");
|
|
|
|
|
worldRef.weather = canonicalWeather(fixed);
|
2026-06-29 16:21:58 +09:00
|
|
|
worldRef.nextWeatherChange = resetTimer();
|
2026-07-05 18:01:36 +09:00
|
|
|
if (previous !== worldRef.weather) {
|
|
|
|
|
worldRef.log?.(`\u5929\u6C17: ${weatherLabel(worldRef.weather)}`);
|
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" &&
|
2026-07-05 18:01:36 +09:00
|
|
|
Math.random() < Math.max(0, Number(dt) || 0) * 0.24
|
2026-06-29 16:21:58 +09:00
|
|
|
);
|
|
|
|
|
}
|
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);
|
2026-07-11 21:13:39 +09:00
|
|
|
drop.rainDrop = opts?.rainDrop === true || (!hasX && !hasY);
|
2026-07-03 20:57:02 +09:00
|
|
|
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";
|
2026-07-05 18:01:36 +09:00
|
|
|
const previous = canonicalWeather(worldRef.weather || "sunny");
|
2026-06-29 16:21:58 +09:00
|
|
|
const next = chooseNext(previous);
|
2026-07-05 18:01:36 +09:00
|
|
|
worldRef.weather = canonicalWeather(next);
|
2026-06-29 16:21:58 +09:00
|
|
|
worldRef.nextWeatherChange = resetTimer();
|
|
|
|
|
if (next !== previous) {
|
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);
|