Compare commits
1 Commits
main
...
feat/progr
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7c3510a680 |
28
game.js
28
game.js
@@ -118,6 +118,9 @@ const G = {
|
|||||||
// Bulk buy multiplier (1, 10, or -1 for max)
|
// Bulk buy multiplier (1, 10, or -1 for max)
|
||||||
buyAmount: 1,
|
buyAmount: 1,
|
||||||
|
|
||||||
|
// Track which buildings have had their unlock toasted
|
||||||
|
seenBuildings: {},
|
||||||
|
|
||||||
// Time tracking
|
// Time tracking
|
||||||
playTime: 0,
|
playTime: 0,
|
||||||
startTime: 0
|
startTime: 0
|
||||||
@@ -1072,6 +1075,21 @@ function tick() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// === TOAST NOTIFICATIONS ===
|
||||||
|
function showToast(title, msg, type) {
|
||||||
|
const container = document.getElementById('toast-container');
|
||||||
|
if (!container) return;
|
||||||
|
const el = document.createElement('div');
|
||||||
|
el.className = `toast toast-${type}`;
|
||||||
|
el.innerHTML = `<div class="toast-title">${title}</div><div class="toast-msg">${msg}</div>`;
|
||||||
|
container.appendChild(el);
|
||||||
|
// Auto-dismiss after 4s
|
||||||
|
setTimeout(() => { el.classList.add('fade-out'); }, 4000);
|
||||||
|
setTimeout(() => { el.remove(); }, 4600);
|
||||||
|
// Cap visible toasts at 4
|
||||||
|
while (container.children.length > 4) container.removeChild(container.firstChild);
|
||||||
|
}
|
||||||
|
|
||||||
function checkMilestones() {
|
function checkMilestones() {
|
||||||
for (const m of MILESTONES) {
|
for (const m of MILESTONES) {
|
||||||
if (!G.milestones.includes(m.flag)) {
|
if (!G.milestones.includes(m.flag)) {
|
||||||
@@ -1089,6 +1107,7 @@ function checkMilestones() {
|
|||||||
if (G.totalCode >= phase.threshold && parseInt(phaseNum) > G.phase) {
|
if (G.totalCode >= phase.threshold && parseInt(phaseNum) > G.phase) {
|
||||||
G.phase = parseInt(phaseNum);
|
G.phase = parseInt(phaseNum);
|
||||||
log(`PHASE ${G.phase}: ${phase.name}`, true);
|
log(`PHASE ${G.phase}: ${phase.name}`, true);
|
||||||
|
showToast(`PHASE ${G.phase}: ${phase.name}`, phase.desc, 'phase');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1161,6 +1180,8 @@ function buyProject(id) {
|
|||||||
G.activeProjects = G.activeProjects.filter(aid => aid !== pDef.id);
|
G.activeProjects = G.activeProjects.filter(aid => aid !== pDef.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
showToast(pDef.milestone ? '★ ' + pDef.name : pDef.name, pDef.desc, 'project');
|
||||||
|
|
||||||
updateRates();
|
updateRates();
|
||||||
render();
|
render();
|
||||||
}
|
}
|
||||||
@@ -1608,6 +1629,12 @@ function renderBuildings() {
|
|||||||
visibleCount++;
|
visibleCount++;
|
||||||
const count = G.buildings[def.id] || 0;
|
const count = G.buildings[def.id] || 0;
|
||||||
|
|
||||||
|
// Toast on first unlock
|
||||||
|
if (isUnlocked && !G.seenBuildings[def.id]) {
|
||||||
|
G.seenBuildings[def.id] = true;
|
||||||
|
showToast('NEW: ' + def.name, def.desc, 'building');
|
||||||
|
}
|
||||||
|
|
||||||
// Locked preview: show dimmed with unlock hint
|
// Locked preview: show dimmed with unlock hint
|
||||||
if (!isUnlocked) {
|
if (!isUnlocked) {
|
||||||
html += `<div class="build-btn" style="opacity:0.25;cursor:default" title="${def.edu || ''}">`;
|
html += `<div class="build-btn" style="opacity:0.25;cursor:default" title="${def.edu || ''}">`;
|
||||||
@@ -1995,6 +2022,7 @@ function saveGame() {
|
|||||||
activeDebuffIds: debuffIds,
|
activeDebuffIds: debuffIds,
|
||||||
totalEventsResolved: G.totalEventsResolved || 0,
|
totalEventsResolved: G.totalEventsResolved || 0,
|
||||||
buyAmount: G.buyAmount || 1,
|
buyAmount: G.buyAmount || 1,
|
||||||
|
seenBuildings: G.seenBuildings || {},
|
||||||
savedAt: Date.now()
|
savedAt: Date.now()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
13
index.html
13
index.html
@@ -84,6 +84,18 @@ body{background:var(--bg);color:var(--text);font-family:'SF Mono','Cascadia Code
|
|||||||
#drift-ending button{margin-top:20px;background:#1a0808;border:1px solid #f44336;color:#f44336;padding:10px 24px;border-radius:4px;cursor:pointer;font-family:inherit;font-size:11px}
|
#drift-ending button{margin-top:20px;background:#1a0808;border:1px solid #f44336;color:#f44336;padding:10px 24px;border-radius:4px;cursor:pointer;font-family:inherit;font-size:11px}
|
||||||
#drift-ending button:hover{background:#2a1010}
|
#drift-ending button:hover{background:#2a1010}
|
||||||
::-webkit-scrollbar{width:4px}::-webkit-scrollbar-track{background:var(--bg)}::-webkit-scrollbar-thumb{background:var(--border);border-radius:2px}
|
::-webkit-scrollbar{width:4px}::-webkit-scrollbar-track{background:var(--bg)}::-webkit-scrollbar-thumb{background:var(--border);border-radius:2px}
|
||||||
|
#toast-container{position:fixed;top:60px;right:16px;z-index:80;display:flex;flex-direction:column;gap:8px;pointer-events:none}
|
||||||
|
.toast{background:#0e1420;border:1px solid #2a3a4a;border-radius:6px;padding:10px 16px;max-width:320px;animation:toast-in 0.3s ease-out;opacity:1;transition:opacity 0.5s ease-out;pointer-events:auto}
|
||||||
|
.toast.fade-out{opacity:0}
|
||||||
|
.toast-phase{border-color:var(--gold);border-width:2px}
|
||||||
|
.toast-phase .toast-title{color:var(--gold);text-shadow:0 0 12px rgba(255,215,0,0.3)}
|
||||||
|
.toast-building{border-color:var(--accent)}
|
||||||
|
.toast-building .toast-title{color:var(--accent)}
|
||||||
|
.toast-project{border-color:var(--green)}
|
||||||
|
.toast-project .toast-title{color:var(--green)}
|
||||||
|
.toast-title{font-size:12px;font-weight:700;letter-spacing:1px;margin-bottom:2px}
|
||||||
|
.toast-msg{font-size:10px;color:#888;line-height:1.4}
|
||||||
|
@keyframes toast-in{from{transform:translateX(100%);opacity:0}to{transform:translateX(0);opacity:1}}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
@@ -160,6 +172,7 @@ Events Resolved: <span id="st-resolved">0</span>
|
|||||||
<h2>SYSTEM LOG</h2>
|
<h2>SYSTEM LOG</h2>
|
||||||
<div id="log-entries"></div>
|
<div id="log-entries"></div>
|
||||||
</div>
|
</div>
|
||||||
|
<div id="toast-container"></div>
|
||||||
<div id="save-toast" style="display:none;position:fixed;top:16px;right:16px;background:#0e1420;border:1px solid #2a3a4a;color:#4a9eff;font-size:10px;padding:6px 12px;border-radius:4px;z-index:50;opacity:0;transition:opacity 0.4s;pointer-events:none">Save</div>
|
<div id="save-toast" style="display:none;position:fixed;top:16px;right:16px;background:#0e1420;border:1px solid #2a3a4a;color:#4a9eff;font-size:10px;padding:6px 12px;border-radius:4px;z-index:50;opacity:0;transition:opacity 0.4s;pointer-events:none">Save</div>
|
||||||
<div id="drift-ending">
|
<div id="drift-ending">
|
||||||
<h2>THE DRIFT</h2>
|
<h2>THE DRIFT</h2>
|
||||||
|
|||||||
Reference in New Issue
Block a user