// ----- GAME DATA (Hardcoded for single-file demo) -----
const upgradeData = [
{
id: "clickUpgrade",
name: "+1 Click per Click",
baseCost: 10,
costMultiplier: 1.5,
effect: { type: "clicksPerClick", amount: 1 },
unlockAt: 0
},
{
id: "autoClickUpgrade",
name: "Auto Clicker (1 CPS)",
baseCost: 50,
costMultiplier: 1.7,
effect: { type: "autoClicksPerSecond", amount: 1 },
unlockAt: 20
}
];
const achievementData = [
{ id:"first10Clicks", name:"First 10 clicks", condition:"clicks >= 10", reward:{clicks:10}, rewardDescription:"+10 clicks" },
{ id:"reached100Clicks", name:"Reached 100 clicks", condition:"clicks >= 100", reward:{clicks:50}, rewardDescription:"+50 clicks" },
{ id:"firstClickUpgrade", name:"First Click Upgrade", condition:"clicksPerClick > 1", reward:{clicksPerClick:1}, rewardDescription:"+1 clicks per click" },
{ id:"firstAutoClicker", name:"First Auto Clicker", condition:"autoClicksPerSecond > 0", reward:{autoClicksPerSecond:1}, rewardDescription:"+1 auto CPS" }
];
const levelData = [
{ level:1, requiredTotalCoins:0, rewards:["+1 clicksPerClick"] },
{ level:2, requiredTotalCoins:100, rewards:["+5 clicks"] },
{ level:3, requiredTotalCoins:250, rewards:["+1 autoClicksPerSecond"] }
];
// --- GLOBALS
let clicks = 0, totalCoins = 0, clicksPerClick = 1, autoClicksPerSecond = 0, currentLevel = 1;
let upgrades = {}, unlockedUpgrades = {}, achievements = {}, lastUpdate = Date.now();
let moneyCircleActive = false;
// ----- DOM ELEMENTS
const shopEl = document.getElementById("shop");
const clickCountEl = document.getElementById("clickCount");
const autoCPSCountEl = document.getElementById("autoCPSCount");
const clickButton = document.getElementById("clickButton");
const achievementListEl = document.getElementById("achievementList");
const achievementButton = document.getElementById("achievementButton");
const achievementMenuEl = document.getElementById("achievementMenu");
const closeAchievementMenuBtn = document.getElementById("closeAchievementMenu");
const settingsPanel = document.getElementById("settingsPanel");
const settingsButton = document.getElementById("settingsButton");
const closeSettingsBtn = document.getElementById("closeSettingsBtn");
const shopSideSelect = document.getElementById("shopSideSelect");
const shopColorInput = document.getElementById("shopColorInput");
const offlinePopup = document.getElementById("offlinePopup");
const resetBtn = document.getElementById("resetProgressBtn");
const circleStatusEl = document.getElementById("circleStatus");
const toggleConsoleBtn = document.getElementById("toggleConsoleBtn");
const consoleContainer = document.getElementById("consoleContainer");
const consoleOutput = document.getElementById("consoleOutput");
const consoleInput = document.getElementById("consoleInput");
// -------- SAVING/LOADING
function saveAll() {
localStorage.setItem("clicks", clicks);
localStorage.setItem("totalCoins", totalCoins);
localStorage.setItem("clicksPerClick", clicksPerClick);
localStorage.setItem("autoClicksPerSecond", autoClicksPerSecond);
localStorage.setItem("upgrades", JSON.stringify(upgrades));
localStorage.setItem("unlockedUpgrades", JSON.stringify(unlockedUpgrades));
localStorage.setItem("achievements", JSON.stringify(achievements));
localStorage.setItem("currentLevel", currentLevel);
localStorage.setItem("lastUpdate", Date.now());
localStorage.setItem("shopSide", shopEl.classList.contains("right") ? "right" : "left");
localStorage.setItem("shopColor", shopEl.style.backgroundColor);
}
function loadAll() {
clicks = parseInt(localStorage.getItem("clicks")) || 0;
totalCoins = parseInt(localStorage.getItem("totalCoins")) || 0;
clicksPerClick = parseInt(localStorage.getItem("clicksPerClick")) || 1;
autoClicksPerSecond = parseInt(localStorage.getItem("autoClicksPerSecond")) || 0;
upgrades = JSON.parse(localStorage.getItem("upgrades")) || {};
unlockedUpgrades = JSON.parse(localStorage.getItem("unlockedUpgrades")) || {};
achievements = JSON.parse(localStorage.getItem("achievements")) || {};
currentLevel = parseInt(localStorage.getItem("currentLevel")) || 1;
lastUpdate = parseInt(localStorage.getItem("lastUpdate")) || Date.now();
// Apply shop side/color
const side = localStorage.getItem("shopSide") || "left";
if (side === "right") shopEl.classList.add("right"); else shopEl.classList.remove("right");
const color = localStorage.getItem("shopColor") || "#eeeeee";
shopEl.style.backgroundColor = color;
shopSideSelect.value = side; shopColorInput.value = color;
}
function handleIdleProgress() {
const now = Date.now();
const elapsed = Math.floor((now - lastUpdate) / 1000);
if (elapsed > 0) {
const idle = Math.floor(elapsed * autoClicksPerSecond / 100);
if (idle > 0) {
clicks += idle; totalCoins += idle;
showOfflinePopup(idle);
saveAll();
}
}
lastUpdate = now;
}
function showOfflinePopup(amount) {
offlinePopup.textContent = `Welcome back! You earned ${amount} clicks offline.`;
offlinePopup.style.display = "block";
setTimeout(()=>{offlinePopup.style.display="none";}, 5000);
}
// ------- UPGRADES/SHOP
function getUpgradeCost(upg) {
const n = upgrades[upg.id] || 0;
return Math.floor(upg.baseCost * Math.pow(upg.costMultiplier, n));
}
function recalcStats() {
clicksPerClick = 1; autoClicksPerSecond = 0;
upgradeData.forEach(upg => {
const n = upgrades[upg.id] || 0;
if (upg.effect.type === "clicksPerClick") clicksPerClick += upg.effect.amount * n;
if (upg.effect.type === "autoClicksPerSecond") autoClicksPerSecond += upg.effect.amount * n;
});
}
function buyUpgrade(id) {
const upg = upgradeData.find(u=>u.id===id);
if (!upg) return false;
const cost = getUpgradeCost(upg);
if (clicks >= cost) {
clicks -= cost; upgrades[id]=(upgrades[id]||0)+1;
recalcStats(); saveAll(); updateShopUI();
return true;
}
return false;
}
function checkUnlockUpgrades() {
upgradeData.forEach(up => {
if ((up.unlockAt||0) <= clicks)
if (!unlockedUpgrades[up.id]) unlockedUpgrades[up.id]=true;
});
}
function updateShopUI() {
shopEl.innerHTML = "
Upgrades
";
upgradeData.forEach(upg => {
if (unlockedUpgrades[upg.id] || (upg.unlockAt||0)<=clicks) {
const div = document.createElement("div");
div.style.marginBottom="10px";
const btn = document.createElement("button");
btn.id = `btn-${upg.id}`;
const cost = getUpgradeCost(upg);
btn.textContent = `${upg.name} (Cost: ${cost})`;
btn.disabled = clicks < cost;
btn.onclick = () => buyUpgrade(upg.id) && updateUI();
const span = document.createElement("span");
span.textContent = upgrades[upg.id]||0; span.style.marginLeft="10px";
div.appendChild(btn); div.appendChild(span); shopEl.appendChild(div);
}
});
}
// ------- ACHIEVEMENTS/LEVELS
function updateAchievementsDisplay() {
achievementListEl.innerHTML = "";
achievementData.forEach(ach => {
const state = achievements[ach.id];
if (state) {
const li = document.createElement("li");
li.textContent = ach.name + (state==="unclaimed" ? " (unclaimed)" : " (claimed)");
if (state==="unclaimed") {
const claimBtn = document.createElement("button");
claimBtn.textContent="Claim"; claimBtn.style.marginLeft="10px";
claimBtn.onclick = ()=>claimAchievement(ach);
li.appendChild(claimBtn);
}
achievementListEl.appendChild(li);
}
});
}
function claimAchievement(ach) {
if (achievements[ach.id]==="unclaimed") {
achievements[ach.id]="claimed";
applyAchievementReward(ach); saveAll();
updateAchievementsDisplay(); updateUI();
alert(`Achievement claimed: ${ach.name}`);
}
}
function checkAchievements() {
let updated = false;
achievementData.forEach(ach => {
if (!achievements[ach.id]) {
try {
const condStr = ach.condition.replace(/clicks/g, clicks)
.replace(/clicksPerClick/g, clicksPerClick)
.replace(/autoClicksPerSecond/g, autoClicksPerSecond)
.replace(/moneyCircleActive/g, moneyCircleActive ? "true":"false");
if (eval(condStr)) {
achievements[ach.id]="unclaimed"; updated=true;
}
} catch(e){}
}
});
if (updated) { saveAll(); updateAchievementsDisplay(); }
}
function applyAchievementReward(ach) {
if(!ach.reward)return;
if(ach.reward.clicks){ clicks+=ach.reward.clicks; totalCoins+=ach.reward.clicks;}
if(ach.reward.clicksPerClick) clicksPerClick+=ach.reward.clicksPerClick;
if(ach.reward.autoClicksPerSecond) autoClicksPerSecond+=ach.reward.autoClicksPerSecond;
updateShopUI(); updateUI();
}
function checkLevelUp() {
let nextLevel=currentLevel+1, leveledUp=false;
while(1){
const lvl = levelData.find(l=>l.level===nextLevel); if(!lvl)break;
if(totalCoins>=lvl.requiredTotalCoins){
currentLevel=nextLevel; leveledUp=true;
alert(`Level up! Now level ${currentLevel}.`);
lvl.rewards.forEach(r=>{
if(r.includes('clicksPerClick'))clicksPerClick++;
else if(r.includes('autoClicksPerSecond'))autoClicksPerSecond++;
else if(r.includes('clicks')){const n=parseInt(r.match(/\d+/)[0]); clicks+=n; totalCoins+=n;}
}); saveAll(); nextLevel++;
} else break;
} if(leveledUp) updateUI();
}
// ---------- UI
function updateUI() {
clickCountEl.textContent = clicks;
autoCPSCountEl.textContent = autoClicksPerSecond;
updateShopUI();
updateAchievementsDisplay();
circleStatusEl.textContent = moneyCircleActive ? "💰 Money Circle Active! Double earnings now!" : "";
}
resetBtn.onclick=function(){if(confirm("Reset all progress?")){localStorage.clear();location.reload();}}
// ---------- SETTINGS
shopSideSelect.onchange = () => {
if(shopSideSelect.value==="right")shopEl.classList.add("right");
else shopEl.classList.remove("right");
localStorage.setItem("shopSide", shopSideSelect.value);
};
shopColorInput.oninput = () => {
shopEl.style.backgroundColor = shopColorInput.value;
localStorage.setItem("shopColor", shopColorInput.value);
};
settingsButton.onclick = ()=>{
if(achievementMenuEl.style.display==="block")achievementMenuEl.style.display="none";
settingsPanel.style.display = settingsPanel.style.display==="block"?"none":"block";
};
closeSettingsBtn.onclick = ()=>{settingsPanel.style.display="none";}
// ------- ACHIEVEMENT MENU
achievementButton.onclick=function(){
if(settingsPanel.style.display==="block")settingsPanel.style.display="none";
achievementMenuEl.style.display = achievementMenuEl.style.display==="block"?"none":"block";
};
closeAchievementMenuBtn.onclick=()=>{achievementMenuEl.style.display="none";}
// ---------- CONSOLE
toggleConsoleBtn.onclick = () => {
consoleContainer.style.display = consoleContainer.style.display==="block"?"none":"block";
if(consoleContainer.style.display==="block")consoleInput.focus();
};
consoleInput.onkeydown = e => {
if(e.key==="Enter"){ handleConsoleCommand(consoleInput.value.trim()); consoleInput.value="";}
};
function writeConsole(text) {
const el = document.createElement("div");
el.textContent = text; consoleOutput.appendChild(el);
consoleOutput.scrollTop = consoleOutput.scrollHeight;
}
function handleConsoleCommand(cmd) {
const parts = cmd.split(" "), command = (parts[0]||"").toLowerCase();
if(command==="ethemcoin"){
const op = parts[1], amount = parseInt(parts[2]);
if((op==="+"||op==="-")&&!isNaN(amount)){
if(op==="+"){clicks+=amount;totalCoins+=amount;writeConsole(`Added ${amount} coins.`);}
else{clicks=Math.max(0,clicks-amount);writeConsole(`Subtracted ${amount} coins.`);}
checkUnlockUpgrades(); updateShopUI(); updateUI(); saveAll();
} else writeConsole("Usage: ethemcoin [+|-] (number)");
} else if(command==="listallupgrades"){
upgradeData.forEach((up,i)=>writeConsole(`${i+1}:${up.name}, Owned:${upgrades[up.id]||0}, Unlock At:${up.unlockAt||0}`));
} else if(command==="ethemupgrade"){
const index = parseInt(parts[1])-1, amount=parseInt(parts[2])||1;
if(index>=0&&index{
moneyCircleActive = false; updateUI(); saveAll();
scheduleMoneyCircle();
},2*60*1000);
}
// --------- MAIN LOGIC
function main(){
loadAll();
handleIdleProgress();
recalcStats();
checkUnlockUpgrades();
updateShopUI();
updateAchievementsDisplay();
updateUI();
setupGameLoop();
scheduleMoneyCircle();
}
function setupGameLoop(){
clickButton.onclick = ()=> {
let gain=clicksPerClick*(moneyCircleActive?2:1);
clicks+=gain; totalCoins+=gain;
checkUnlockUpgrades(); checkAchievements(); updateShopUI(); updateAchievementsDisplay(); updateUI(); saveAll(); checkLevelUp();
};
setInterval(()=>{
let gain=autoClicksPerSecond*(moneyCircleActive?2:1);
clicks+=gain; totalCoins+=gain;
checkUnlockUpgrades(); checkAchievements(); updateShopUI(); updateAchievementsDisplay(); updateUI(); saveAll(); checkLevelUp();
},1000);
}
main();