Skip to content

Commit 6ea12f9

Browse files
authored
Add force surge effect (#283)
1 parent 3e5ca8b commit 6ea12f9

File tree

3 files changed

+84
-13
lines changed

3 files changed

+84
-13
lines changed

src/_includes/footer-details.njk

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,14 @@
2020

2121
<div class="flex flex-col items-center md:items-end gap-2">
2222
<div class="flex items-center gap-3">
23-
<span class="w-2 h-2 rounded-full bg-green-500 animate-pulse"></span>
23+
<button
24+
id="footer-surge-button"
25+
onclick="handleFooterDotClick()"
26+
class="relative flex h-6 w-6 items-center justify-center focus:outline-none group cursor-pointer"
27+
>
28+
<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>
29+
<span id="footer-dot-core" class="relative inline-flex rounded-full h-4 w-4 bg-green-500 transition-colors duration-500"></span>
30+
</button>
2431
<span class="text-[var(--text-muted)] text-[10px] font-black uppercase tracking-widest">Build: {{ build.timestamp }}</span>
2532
</div>
2633

src/assets/css/style.css

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -539,8 +539,8 @@ body[data-level="6"]::after {
539539
--glow-color: #38bdf8; /* Default Jedi Blue */
540540
position: relative;
541541
z-index: 10;
542-
transition: all 0.3s ease;
543-
animation: force-pulse 5s infinite ease-in-out;
542+
transition: all 0.5s ease;
543+
animation: force-pulse 10s infinite ease-in-out;
544544
}
545545

546546
/* Sith Variant (Red Glow) */
@@ -581,9 +581,6 @@ body[data-level="6"]::after {
581581
}
582582
}
583583

584-
.force-glow {
585-
animation: force-pulse 1.5s infinite ease-in-out;
586-
}
587584
#level-name {
588585
font-weight: 900;
589586
text-transform: uppercase;

src/assets/js/script.js

Lines changed: 74 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ let currentLevel = Number(localStorage.getItem("userLevel")) || 0;
66
// Load saved XP or start at 0
77
let currentXP = parseInt(localStorage.getItem("userXP")) || 0;
88

9+
let isSurging = false;
10+
911
function getContrastYIQ(hexcolor) {
1012
hexcolor = hexcolor.replace("#", "");
1113
var r = parseInt(hexcolor.substr(0, 2), 16);
@@ -393,8 +395,16 @@ function updateThemeIcon(theme) {
393395
* 5. EASTER EGG LOGIC & TRIGGERS
394396
*/
395397
function triggerForceSurge() {
398+
if (isSurging) return; // Prevent overlapping surges
399+
400+
isSurging = true;
396401
initAudio();
397-
addExperience(100); // This now handles UI updates, sounds, and bar filling
402+
addExperience(1000);
403+
404+
// Reset after the animation duration (e.g., 1 second)
405+
setTimeout(() => {
406+
isSurging = false;
407+
}, 10000);
398408
}
399409

400410
function triggerMagicXP() {
@@ -403,12 +413,15 @@ function triggerMagicXP() {
403413
}
404414

405415
// Visual Effect for Level 101+
406-
function triggerForceEffects(lvl) {
416+
function triggerForceEffects() {
407417
const badge = document.getElementById("level-badge");
408418
if (badge) {
409419
badge.classList.add("force-glow");
410420
// Remove after 2 seconds unless it's a persistent rank
411-
setTimeout(() => badge.classList.remove("force-glow"), 2000);
421+
setTimeout(() => badge.classList.remove("force-glow"), 5000);
422+
console.log("Trigger Force Effects");
423+
} else {
424+
console.log("Badge not found");
412425
}
413426
}
414427

@@ -980,7 +993,6 @@ async function addExperience(amount) {
980993

981994
console.log(`Leveled Up to ${currentLevel}!`);
982995
}
983-
984996
// 4. Persistence: Save clean numbers
985997
localStorage.setItem("userLevel", currentLevel.toString());
986998
localStorage.setItem("userXP", currentXP.toString());
@@ -1092,7 +1104,6 @@ function updateGameUI() {
10921104
document.getElementById("total-xp-display").innerText =
10931105
`${currentXP} / ${XP_PER_LEVEL}`;
10941106
}
1095-
10961107
renderXP(currentXP);
10971108
}
10981109

@@ -1215,14 +1226,70 @@ function jumpToLevel() {
12151226

12161227
const rank = getRank(currentLevel);
12171228
showLevelUpNotification(rank);
1229+
}
1230+
1231+
function handleFooterDotClick() {
1232+
// 1. Get the current list of unlocked eggs
1233+
const rawEggs = localStorage.getItem("unlockedEggs") || "[]";
1234+
const unlockedEggs = JSON.parse(rawEggs);
1235+
1236+
// 2. Exit if already unlocked
1237+
if (unlockedEggs.includes("footer_surge")) return;
12181238

1219-
if (currentLevel >= 101) {
1239+
let clicks = parseInt(localStorage.getItem("footerDotClicks")) || 0;
1240+
clicks++;
1241+
1242+
const core = document.getElementById("footer-dot-core");
1243+
const ping = document.getElementById("footer-dot-ping");
1244+
1245+
if (clicks >= 10) {
1246+
// Trigger the main function
12201247
triggerForceSurge();
1248+
1249+
// 3. Update the global unlockedEggs array
1250+
unlockedEggs.push("footer_surge");
1251+
localStorage.setItem("unlockedEggs", JSON.stringify(unlockedEggs));
1252+
1253+
// Cleanup temporary click counter
1254+
localStorage.removeItem("footerDotClicks");
1255+
1256+
finalizeFooterDot(core, ping);
1257+
} else {
1258+
updateFooterDotVisuals(clicks, core, ping);
1259+
localStorage.setItem("footerDotClicks", clicks);
1260+
}
1261+
}
1262+
1263+
function updateFooterDotVisuals(count, core, ping) {
1264+
if (count >= 4 && count < 8) {
1265+
core.classList.replace("bg-green-500", "bg-yellow-500");
1266+
ping.classList.replace("bg-green-400", "bg-yellow-400");
1267+
} else if (count >= 8) {
1268+
core.classList.replace("bg-yellow-500", "bg-red-500");
1269+
ping.classList.replace("bg-yellow-400", "bg-red-400");
12211270
}
12221271
}
12231272

1273+
function finalizeFooterDot(core, ping) {
1274+
// Switch to a "spent" state (Indigo)
1275+
core.classList.remove("bg-red-500", "bg-green-500", "bg-yellow-500");
1276+
core.classList.add("bg-indigo-500");
1277+
ping.classList.add("hidden");
1278+
document.getElementById("footer-surge-button").style.cursor = "default";
1279+
}
1280+
12241281
// Re-initialize skills after Surprise scroll or any DOM changes
1225-
window.addEventListener("DOMContentLoaded", initSkillXP);
1282+
window.addEventListener("DOMContentLoaded", () => {
1283+
initSkillXP();
1284+
1285+
const unlockedEggs = JSON.parse(localStorage.getItem("unlockedEggs") || "[]");
1286+
if (unlockedEggs.includes("footer_surge")) {
1287+
finalizeFooterDot(
1288+
document.getElementById("footer-dot-core"),
1289+
document.getElementById("footer-dot-ping"),
1290+
);
1291+
}
1292+
});
12261293

12271294
/**
12281295
* INITIALIZATION

0 commit comments

Comments
 (0)