sounds
This commit is contained in:
parent
c6ba3e38a2
commit
37087d08a7
189 changed files with 12864 additions and 9589 deletions
181
js/ui_log.js
Normal file
181
js/ui_log.js
Normal file
|
|
@ -0,0 +1,181 @@
|
|||
"use strict";
|
||||
|
||||
function loadLogPushSettings() {
|
||||
try {
|
||||
const raw = localStorage.getItem("tarinai_log_push_settings_v2");
|
||||
if (!raw) return;
|
||||
const parsed = JSON.parse(raw);
|
||||
uiCache.logPushEnabled = Boolean(parsed.enabled);
|
||||
if (Array.isArray(parsed.kinds)) uiCache.logPushKinds = new Set(parsed.kinds);
|
||||
} catch (_) {}
|
||||
}
|
||||
|
||||
function saveLogPushSettings() {
|
||||
try {
|
||||
localStorage.setItem("tarinai_log_push_settings_v2", JSON.stringify({
|
||||
enabled: Boolean(uiCache.logPushEnabled),
|
||||
kinds: Array.from(uiCache.logPushKinds || []),
|
||||
}));
|
||||
} catch (_) {}
|
||||
}
|
||||
|
||||
function syncLogPushControls() {
|
||||
if (ui.logPushEnabled) ui.logPushEnabled.checked = Boolean(uiCache.logPushEnabled);
|
||||
for (const input of ui.logPushControls?.querySelectorAll("[data-push-kind]") || []) {
|
||||
input.checked = uiCache.logPushKinds?.has(input.dataset.pushKind || "") ?? false;
|
||||
}
|
||||
}
|
||||
|
||||
function syncAudioControls() {
|
||||
if (!window.TarinaiAudio) return;
|
||||
for (const input of ui.soundCategoryControls?.querySelectorAll("[data-sound-category]") || []) {
|
||||
const category = input.dataset.soundCategory || "";
|
||||
input.checked = audio.categoryOn ? audio.categoryOn(category) : true;
|
||||
input.disabled = !audio.enabled;
|
||||
}
|
||||
if (ui.soundMasterToggle) ui.soundMasterToggle.checked = Boolean(audio.enabled);
|
||||
if (ui.soundBtn) {
|
||||
ui.soundBtn.textContent = audio.enabled ? "音設定 ON" : "音設定 OFF";
|
||||
ui.soundBtn.classList.toggle("active", Boolean(audio.enabled));
|
||||
ui.soundBtn.setAttribute("aria-expanded", ui.soundPanel && !ui.soundPanel.classList.contains("hidden") ? "true" : "false");
|
||||
}
|
||||
}
|
||||
|
||||
function closeSoundPanel() {
|
||||
ui.soundPanel?.classList.add("hidden");
|
||||
syncAudioControls();
|
||||
}
|
||||
|
||||
function toggleSoundPanel() {
|
||||
if (audio.enabled) audio.uiClick?.();
|
||||
ui.soundPanel?.classList.toggle("hidden");
|
||||
syncAudioControls();
|
||||
}
|
||||
|
||||
function pushLogNotification(entry = {}) {
|
||||
if (!uiCache.logPushEnabled || !entry || entry.hiddenFromObservation) return;
|
||||
const kind = entry.kind || "note";
|
||||
if (!uiCache.logPushKinds?.has(kind)) return;
|
||||
const overlay = ui.logPushOverlay;
|
||||
audio.notify?.();
|
||||
if (!overlay) return;
|
||||
const card = document.createElement("div");
|
||||
card.className = `log-push-toast log-push-${kind}`;
|
||||
const tag = document.createElement("span");
|
||||
tag.className = "log-push-tag";
|
||||
tag.textContent = logKindLabel(kind);
|
||||
const time = document.createElement("span");
|
||||
time.className = "log-push-time";
|
||||
time.textContent = formatLogTime(entry.time || 0);
|
||||
const text = document.createElement("div");
|
||||
text.className = "log-push-text";
|
||||
text.textContent = formatLogDisplayText(entry.text || "");
|
||||
card.appendChild(tag);
|
||||
card.appendChild(time);
|
||||
card.appendChild(text);
|
||||
overlay.prepend(card);
|
||||
while (overlay.children.length > 5) overlay.lastElementChild?.remove();
|
||||
window.setTimeout(() => {
|
||||
card.classList.add("leaving");
|
||||
window.setTimeout(() => card.remove(), 220);
|
||||
}, 5200);
|
||||
}
|
||||
|
||||
window.pushLogNotification = pushLogNotification;
|
||||
|
||||
function renderLog(logs) {
|
||||
ui.log.innerHTML = "";
|
||||
const frag = document.createDocumentFragment();
|
||||
for (const raw of logs.slice(0, 32)) {
|
||||
const entry = typeof raw === "string" ? { time: world.time, text: raw, kind: "note" } : raw;
|
||||
const kind = entry.kind || "note";
|
||||
const div = document.createElement("div");
|
||||
div.className = `log-entry log-${kind}`;
|
||||
const tag = document.createElement("span");
|
||||
tag.className = "log-tag";
|
||||
tag.textContent = logKindLabel(kind);
|
||||
const time = document.createElement("span");
|
||||
time.className = "time";
|
||||
time.textContent = formatLogTime(entry.time || 0);
|
||||
div.appendChild(tag);
|
||||
div.appendChild(time);
|
||||
div.append(document.createTextNode(formatLogDisplayText(entry.text || "")));
|
||||
frag.appendChild(div);
|
||||
}
|
||||
ui.log.appendChild(frag);
|
||||
}
|
||||
|
||||
function formatLogTime(timeValue) {
|
||||
const t = Math.max(0, Number(timeValue) || 0);
|
||||
const day = Math.floor(t / CONFIG.dayLength) + 1;
|
||||
const dayT = ((t % CONFIG.dayLength) + CONFIG.dayLength) % CONFIG.dayLength;
|
||||
const totalMinutes = Math.floor(dayT / CONFIG.dayLength * 24 * 60);
|
||||
const hh = String(Math.floor(totalMinutes / 60)).padStart(2, "0");
|
||||
const mm = String(totalMinutes % 60).padStart(2, "0");
|
||||
return `${day}\u65e5 ${hh}\u6642${mm}\u5206`;
|
||||
}
|
||||
|
||||
function logKindLabel(kind) {
|
||||
return {
|
||||
birth: "\u8a95\u751f", death: "\u6b7b\u4ea1", fight: "\u55a7\u5629", food: "\u98df\u4e8b", grass: "\u8349",
|
||||
weather: "\u74b0\u5883", relation: "\u95a2\u4fc2", accident: "\u4e8b\u6545", observe: "\u89b3\u5bdf", note: "\u8a18\u9332"
|
||||
}[kind] || "\u8a18\u9332";
|
||||
}
|
||||
|
||||
function tarinaiSpritePathForId(id) {
|
||||
const live = world?.tarinai?.find(t => (t.id === id || t.familyKey === id) && !t.dead);
|
||||
const sid = live?.spriteId ? live.spriteId() : live?.type;
|
||||
const fam = world?.family?.[id];
|
||||
const fallback = fam?.type;
|
||||
return (SPRITES.find(s => s.id === (sid || fallback)) || SPRITES[0]).path;
|
||||
}
|
||||
|
||||
function relationIconHtml(id) {
|
||||
if (!id) return "";
|
||||
return `<img class="relation-face" src="${tarinaiSpritePathForId(id)}" alt="">`;
|
||||
}
|
||||
|
||||
function relationEntries(t, kind = "friend") {
|
||||
const rows = [];
|
||||
const liveIds = new Set((world?.tarinai || []).filter(o => o && !o.dead && o !== t).map(o => o.id));
|
||||
for (const [id, rel] of Object.entries(t?.relationships || {})) {
|
||||
if (!liveIds.has(id)) continue;
|
||||
const score = kind === "enemy" ? (rel.fear || 0) : (rel.affinity || 0);
|
||||
const threshold = kind === "enemy" ? 0.5 : FRIEND_AFFINITY_THRESHOLD;
|
||||
if (score <= threshold) continue;
|
||||
rows.push({ id, score, name: relationDisplayName(world, id) });
|
||||
}
|
||||
rows.sort((a, b) => b.score - a.score || a.name.localeCompare(b.name, "ja"));
|
||||
return rows;
|
||||
}
|
||||
|
||||
function relationListHtml(t, kind = "friend") {
|
||||
const rows = relationEntries(t, kind);
|
||||
if (!rows.length) return "\u306a\u3057";
|
||||
const sign = kind === "friend" ? "+" : "";
|
||||
return `<div class="relation-chip-list">${rows.map(r => `
|
||||
<button type="button" class="relation-chip ${kind === "enemy" ? "enemy" : "friend"}" data-focus-tarinai-id="${escapeHtml(r.id)}" title="${escapeHtml(r.name)}\u3078\u79fb\u52d5">
|
||||
${relationIconHtml(r.id)}
|
||||
<span class="relation-chip-name">${escapeHtml(r.name)}</span>
|
||||
<em>${sign}${fmt(r.score)}</em>
|
||||
</button>`).join("")}</div>`;
|
||||
}
|
||||
|
||||
function focusTarinaiById(id) {
|
||||
const t = world?.tarinai?.find(o => o && !o.dead && (o.id === id || o.familyKey === id));
|
||||
if (!t) { showToast("\u305d\u306e\u500b\u4f53\u306f\u3082\u3046\u9078\u629e\u3067\u304d\u307e\u305b\u3093\u3002"); return false; }
|
||||
world.selected = t;
|
||||
t.focusPulseTimer = Math.max(t.focusPulseTimer || 0, 1.25);
|
||||
selectTool("observe");
|
||||
if (Number.isFinite(t.x) && Number.isFinite(t.y)) {
|
||||
world.cameraX = t.x - (world.visibleWorldW ? world.visibleWorldW() : (world.viewportW || world.w)) / 2;
|
||||
world.cameraY = t.y - (world.visibleWorldH ? world.visibleWorldH() : (world.viewportH || world.h)) / 2;
|
||||
world.clampCamera?.();
|
||||
}
|
||||
uiCache.selectedSnapshot = "";
|
||||
renderSelected();
|
||||
renderStats();
|
||||
render?.();
|
||||
showToast(`\u300c${t.name}\u300d\u3078\u79fb\u52d5\u3057\u307e\u3057\u305f\u3002`);
|
||||
return true;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue