tarinai/js/weather_system.js

93 lines
3.2 KiB
JavaScript
Raw Normal View History

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);