Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion src/_includes/footer-details.njk
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,14 @@

<div class="flex flex-col items-center md:items-end gap-2">
<div class="flex items-center gap-3">
<span class="w-2 h-2 rounded-full bg-green-500 animate-pulse"></span>
<button
id="footer-surge-button"
onclick="handleFooterDotClick()"
class="relative flex h-6 w-6 items-center justify-center focus:outline-none group cursor-pointer"
>
<span id="footer-dot-ping" class="animate-ping absolute inline-flex h-full w-full rounded-full bg-green-400 opacity-75 transition-colors duration-500"></span>
<span id="footer-dot-core" class="relative inline-flex rounded-full h-4 w-4 bg-green-500 transition-colors duration-500"></span>
</button>
<span class="text-[var(--text-muted)] text-[10px] font-black uppercase tracking-widest">Build: {{ build.timestamp }}</span>
</div>

Expand Down
7 changes: 2 additions & 5 deletions src/assets/css/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -539,8 +539,8 @@ body[data-level="6"]::after {
--glow-color: #38bdf8; /* Default Jedi Blue */
position: relative;
z-index: 10;
transition: all 0.3s ease;
animation: force-pulse 5s infinite ease-in-out;
transition: all 0.5s ease;
animation: force-pulse 10s infinite ease-in-out;
}

/* Sith Variant (Red Glow) */
Expand Down Expand Up @@ -581,9 +581,6 @@ body[data-level="6"]::after {
}
}

.force-glow {
animation: force-pulse 1.5s infinite ease-in-out;
}
#level-name {
font-weight: 900;
text-transform: uppercase;
Expand Down
81 changes: 74 additions & 7 deletions src/assets/js/script.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ let currentLevel = Number(localStorage.getItem("userLevel")) || 0;
// Load saved XP or start at 0
let currentXP = parseInt(localStorage.getItem("userXP")) || 0;

let isSurging = false;

function getContrastYIQ(hexcolor) {
hexcolor = hexcolor.replace("#", "");
var r = parseInt(hexcolor.substr(0, 2), 16);
Expand Down Expand Up @@ -393,8 +395,16 @@ function updateThemeIcon(theme) {
* 5. EASTER EGG LOGIC & TRIGGERS
*/
function triggerForceSurge() {
if (isSurging) return; // Prevent overlapping surges

isSurging = true;
initAudio();
addExperience(100); // This now handles UI updates, sounds, and bar filling
addExperience(1000);

// Reset after the animation duration (e.g., 1 second)
setTimeout(() => {
isSurging = false;
}, 10000);
}

function triggerMagicXP() {
Expand All @@ -403,12 +413,15 @@ function triggerMagicXP() {
}

// Visual Effect for Level 101+
function triggerForceEffects(lvl) {
function triggerForceEffects() {
const badge = document.getElementById("level-badge");
if (badge) {
badge.classList.add("force-glow");
// Remove after 2 seconds unless it's a persistent rank
setTimeout(() => badge.classList.remove("force-glow"), 2000);
setTimeout(() => badge.classList.remove("force-glow"), 5000);
console.log("Trigger Force Effects");
} else {
console.log("Badge not found");
}
}

Expand Down Expand Up @@ -980,7 +993,6 @@ async function addExperience(amount) {

console.log(`Leveled Up to ${currentLevel}!`);
}

// 4. Persistence: Save clean numbers
localStorage.setItem("userLevel", currentLevel.toString());
localStorage.setItem("userXP", currentXP.toString());
Expand Down Expand Up @@ -1092,7 +1104,6 @@ function updateGameUI() {
document.getElementById("total-xp-display").innerText =
`${currentXP} / ${XP_PER_LEVEL}`;
}

renderXP(currentXP);
}

Expand Down Expand Up @@ -1215,14 +1226,70 @@ function jumpToLevel() {

const rank = getRank(currentLevel);
showLevelUpNotification(rank);
}

function handleFooterDotClick() {
// 1. Get the current list of unlocked eggs
const rawEggs = localStorage.getItem("unlockedEggs") || "[]";
const unlockedEggs = JSON.parse(rawEggs);

// 2. Exit if already unlocked
if (unlockedEggs.includes("footer_surge")) return;

if (currentLevel >= 101) {
let clicks = parseInt(localStorage.getItem("footerDotClicks")) || 0;
clicks++;

const core = document.getElementById("footer-dot-core");
const ping = document.getElementById("footer-dot-ping");

if (clicks >= 10) {
// Trigger the main function
triggerForceSurge();

// 3. Update the global unlockedEggs array
unlockedEggs.push("footer_surge");
localStorage.setItem("unlockedEggs", JSON.stringify(unlockedEggs));

// Cleanup temporary click counter
localStorage.removeItem("footerDotClicks");

finalizeFooterDot(core, ping);
} else {
updateFooterDotVisuals(clicks, core, ping);
localStorage.setItem("footerDotClicks", clicks);
}
}

function updateFooterDotVisuals(count, core, ping) {
if (count >= 4 && count < 8) {
core.classList.replace("bg-green-500", "bg-yellow-500");
ping.classList.replace("bg-green-400", "bg-yellow-400");
} else if (count >= 8) {
core.classList.replace("bg-yellow-500", "bg-red-500");
ping.classList.replace("bg-yellow-400", "bg-red-400");
}
}

function finalizeFooterDot(core, ping) {
// Switch to a "spent" state (Indigo)
core.classList.remove("bg-red-500", "bg-green-500", "bg-yellow-500");
core.classList.add("bg-indigo-500");
ping.classList.add("hidden");
document.getElementById("footer-surge-button").style.cursor = "default";
}

// Re-initialize skills after Surprise scroll or any DOM changes
window.addEventListener("DOMContentLoaded", initSkillXP);
window.addEventListener("DOMContentLoaded", () => {
initSkillXP();

const unlockedEggs = JSON.parse(localStorage.getItem("unlockedEggs") || "[]");
if (unlockedEggs.includes("footer_surge")) {
finalizeFooterDot(
document.getElementById("footer-dot-core"),
document.getElementById("footer-dot-ping"),
);
}
});

/**
* INITIALIZATION
Expand Down