/
chewy
/
BDZ_GenAI
Обзор
Документация
Войти
/
chewy
/
BDZ_GenAI
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
scripts/notify.js
147 строк
8 KB
pichugin.sa
Раскидал все по папкам, чтобы нормально выглядел репозиторий
16 ноя 2025, 21:55
16 ноя 2025, 21:55
bd854ee
Код
Авторство
О чём код?
// notify.js - notifications, flash, and lightweight save/load export function notify(msg, type='info', timeout=1400){ const container = document.querySelector('.toast-container') || (()=>{ const c = document.createElement('div'); c.className='toast-container'; document.body.appendChild(c); return c; })(); const t = document.createElement('div'); t.className = 'toast ' + (type||'info'); t.textContent = msg; container.appendChild(t); setTimeout(()=> { t.style.transition = 'transform 220ms ease, opacity 220ms ease'; t.style.opacity = '0'; t.style.transform = 'translateY(-8px)'; setTimeout(()=> { try{ container.removeChild(t); }catch(e){} }, 260); }, Math.max(800, timeout)); } /* Event Log: persistent list of last 5 events (bottom-right), clickable and auto-fade after 4s */ const EVENT_LOG_MAX = 5; const EVENT_FADE_MS = 4000; function ensureEventLog(){ let el = document.getElementById('__eventLog'); if(el) return el; el = document.createElement('div'); el.id = '__eventLog'; el.className = 'event-log'; document.body.appendChild(el); return el; } /* category: 'success'|'warning'|'violation'|'knowledge' */ export function logEvent(message, category='success', meta={}){ const el = ensureEventLog(); const row = document.createElement('div'); row.className = 'event-row ' + category; row.textContent = message; row.dataset.ts = Date.now(); // attach meta for click handling row._meta = meta || {}; // click -> dispatch eventlog:click with meta row.addEventListener('click', ()=>{ try{ document.dispatchEvent(new CustomEvent('eventlog:click',{detail:row._meta})); }catch(e){} // also highlight in journal via event }); // insert at top el.insertBefore(row, el.firstChild); // animate in requestAnimationFrame(()=> row.classList.add('show')); // trim to max while(el.children.length > EVENT_LOG_MAX) el.removeChild(el.lastChild); // auto remove after EVENT_FADE_MS (with fade out) setTimeout(()=>{ row.classList.remove('show'); setTimeout(()=> { try{ if(row.parentNode) row.parentNode.removeChild(row); }catch(e){} }, 360); }, EVENT_FADE_MS); return row; } /* convenience mapping: create event log entry when notify called for certain types */ export function notifyAndLog(msg, type='info', timeout=1400, meta={}){ notify(msg, type, timeout); // choose category for event log let cat = 'success'; if(type === 'success') cat = 'success'; else if(type === 'warn') cat = 'warning'; else if(type === 'violation' || type === 'danger') cat = 'violation'; else if(type === 'info' && (meta && meta.kind === 'knowledge')) cat = 'knowledge'; else if(type === 'info') cat = 'success'; logEvent(msg, cat, meta); } export function flashIcon(id){ const el = document.getElementById(id); if(!el) return; el.animate([{filter:'brightness(1.2)'},{filter:'brightness(1)'}], {duration:260, easing:'ease-out'}); } export function saveGame(){ try{ const state = { inventory: (window.__engine && window.__engine.player && window.__engine.player.inventory) || [], learned: (window.__LanguageSystem && window.__LanguageSystem.learnedPhrases) || [], factions: (window.__RuleEngine && window.__RuleEngine.factions) || {}, reputation: (window.__RuleEngine && window.__RuleEngine.reputation) || 0, timeOfDay: (window.__engine && window.__engine.timeOfDay) || 0, dayLengthSeconds: (window.__engine && window.__engine.dayLengthSeconds) || 300, weather: (window.__engine && window.__engine.weather) || {kind:'clear',timer:0,duration:0}, contracts: (window.__contracts || []), // persist contracts state seed: window.__worldSeed || null, // save current world seed codex: (window.__LanguageSystem && window.__LanguageSystem.codex) || {} }; localStorage.setItem('rogue_proto_save', JSON.stringify(state)); notify('Игра сохранена', 'success', 900); }catch(e){ console.error('save failed', e); notify('Ошибка при сохранении','warn'); } } export function loadGame(){ try{ const raw = localStorage.getItem('rogue_proto_save'); if(!raw) { notify('Сохранений нет', 'warn'); return; } const state = JSON.parse(raw); if(state.inventory && window.__engine && window.__engine.player) window.__engine.player.inventory = state.inventory; if(state.learned && window.__LanguageSystem) window.__LanguageSystem.learnedPhrases = state.learned; if(state.codex && window.__LanguageSystem) window.__LanguageSystem.codex = state.codex; if(state.factions && window.__RuleEngine) window.__RuleEngine.factions = state.factions; if(typeof state.reputation === 'number' && window.__RuleEngine) window.__RuleEngine.reputation = state.reputation; if(typeof state.timeOfDay === 'number' && window.__engine){ window.__engine.timeOfDay = state.timeOfDay; window.__engine.dayLengthSeconds = state.dayLengthSeconds || window.__engine.dayLengthSeconds; window.__engine.weather = state.weather || window.__engine.weather; } if(state.contracts){ window.__contracts = state.contracts; window.__contracts.forEach(c=>{/* ensure shape */}); } const jl = document.getElementById('journalList'); if(jl && state.learned) state.learned.forEach(p=>{ const li = document.createElement('li'); li.textContent = 'Выучено: '+p; jl.appendChild(li); }); // update codex HUD if present try{ document.dispatchEvent(new CustomEvent('codex:updated')); }catch(e){} notify('Сохранение загружено', 'info', 900); }catch(e){ console.error('load failed', e); notify('Ошибка при загрузке','warn'); } } /* emit small custom events on notable actions to let UI show first-action tooltips */ export function emitFirstAction(name){ document.dispatchEvent(new CustomEvent('player:first:'+name)); } /* expose autosave-friendly save/load wrappers under the new key */ export function saveGameToSlot(){ try{ const state = { player: (window.__engine && window.__engine.player) ? {x: window.__engine.player.x, y: window.__engine.player.y, w: window.__engine.player.w, h: window.__engine.player.h, inventory: window.__engine.player.inventory || []} : {}, scaleSetting: (window.__hud && window.__hud.scaleSetting) || (window.__RuleEngine && window.__RuleEngine.scaleSetting) || window.__scaleSetting || 2, reputation: (window.__RuleEngine && window.__RuleEngine.factions) || {}, codex: (window.__LanguageSystem && window.__LanguageSystem.codex) || {}, seed: window.__worldSeed || null, timeOfDay: (window.__engine && window.__engine.timeOfDay) || 0 }; localStorage.setItem('ScaleShift_save_v1', JSON.stringify(state)); notify('Сохранено в слот', 'success', 900); }catch(e){ console.error(e); notify('Ошибка при сохранении', 'warn'); } } export function loadGameFromSlot(){ try{ const raw = localStorage.getItem('ScaleShift_save_v1'); if(!raw){ notify('Сохранений нет в слоте', 'warn'); return; } const s = JSON.parse(raw); if(s.player && window.__engine && window.__engine.player){ window.__engine.player.x = s.player.x; window.__engine.player.y = s.player.y; window.__engine.player.inventory = s.player.inventory || []; } if(s.scaleSetting && typeof HUD !== 'undefined' && HUD.setScale) HUD.setScale(s.scaleSetting); if(s.codex && window.__LanguageSystem) window.__LanguageSystem.codex = s.codex; if(s.reputation && window.__RuleEngine) window.__RuleEngine.factions = s.reputation; notify('Слот загружен', 'info', 900); }catch(e){ console.error(e); notify('Ошибка при загрузке слота','warn'); } }