Skip to content
Open
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
21 changes: 13 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
cookie-clicker
==============
not quite cookie clicker
========================

This is a copy of the publicly available source of the game cookie clicker by orteil.
A playful fork of Cookie Clicker that keeps the core idle game feel but adds a fresh remix layer.

Here is the actual game:
http://orteil.dashnet.org/cookieclicker/
## What's new in this fork

Here is the orteil home page:
http://orteil.dashnet.org/
- **Crumb economy**: clicking and passive production now generate crumbs, a side resource.
- **Not Quite Lab panel**: a new interface in the middle column with live crumb/combo stats.
- **Combo click gameplay**: maintain fast click streaks for scaling bonus cookie bursts.
- **Mission system**: complete themed goals to earn larger crumb rewards.
- **New actions**:
- **Burst Batch** for instant cookie spikes.
- **Street Bakers** for extra passive cookie generation.

## Why this exists

The purpose of this repository is to provide a jumping off point for javascript programming for Coder Dojo members.
This repo started as a coding practice base, and now serves as a bigger sandbox for experimenting with idle-game systems and UI remix ideas.
5 changes: 3 additions & 2 deletions index.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<!DOCTYPE html>
<html>
<head>
<title>Cookie Clicker</title>
<title>Not Quite Cookie Clicker</title>
<!--
Code and graphics copyright Orteil, 2013
Feel free to alter this code to your liking, but please do not re-host it, do not profit from it and do not present it as your own.
Expand All @@ -27,6 +27,7 @@
<script src="ajax.js"></script>
<script src="dungeons.js?v=1.5026"></script>
<script src="main.js?v=1.5031"></script>
<script src="remix.js?v=1"></script>


<script type="text/javascript">
Expand All @@ -47,7 +48,7 @@

<div id="topBar">
<div>
<b>Cookie Clicker</b> &copy; <a href="http://orteil.dashnet.org" target="_blank">Orteil</a>, 2013 - hosted by <a href="http://dashnet.org" target="_blank">DashNet</a> | <a href="http://twitter.com/orteil42" target="_blank">twitter</a> | <a href="http://orteil42.tumblr.com" target="_blank">tumblr</a> | Help? Bugs? Ideas? Check out the <a href="http://forum.dashnet.org" target="_blank">forum</a>! | Chat with us on <a href="http://forum.dashnet.org/discussion/277/irc-chat-channel/p1" target="_blank">IRC</a> | Getting a black screen? Try pressing ctrl-F5!
<b>Not Quite Cookie Clicker</b> | Community remix with new crumb missions, combo play, and street bakers. Original Cookie Clicker concept by Orteil.
<div id="links" style="display:block;position:absolute;right:8px;top:4px;"></div>
</div>
</div>
Expand Down
214 changes: 214 additions & 0 deletions remix.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
(function () {
var saveKey = 'notQuiteCookieClickerSave';

function format(value) {
if (window.Game && typeof Game.Beautify === 'function') {
return Game.Beautify(Math.floor(value));
}
return Math.floor(value).toString();
}

function loadState() {
try {
var raw = localStorage.getItem(saveKey);
if (!raw) return null;
return JSON.parse(raw);
} catch (error) {
return null;
}
}

function saveState(state) {
try {
localStorage.setItem(saveKey, JSON.stringify(state));
} catch (error) {
// Ignore storage failures.
}
}

function boot() {
if (!window.Game || !Game.ready) {
setTimeout(boot, 300);
return;
}

document.title = 'Not Quite Cookie Clicker';
var topTitle = document.querySelector('#topBar b');
if (topTitle) {
topTitle.textContent = 'Not Quite Cookie Clicker';
}

var supportComment = document.getElementById('supportComment');
if (supportComment) {
supportComment.textContent = 'Fuel this weird little bakery experiment!';
}

var state = Object.assign(
{
crumbs: 0,
combos: 0,
bestCombo: 0,
lastClickAt: 0,
passiveBakers: 0,
fulfilledMissions: {},
lifetimeCrumbs: 0,
},
loadState() || {}
);

var missions = [
{
id: 'first1000',
label: 'Bake 1,000 cookies',
target: function () {
return 1000;
},
progress: function () {
return Game.cookiesEarned;
},
reward: 15,
},
{
id: 'combo10',
label: 'Reach a 10-click combo',
target: function () {
return 10;
},
progress: function () {
return state.bestCombo;
},
reward: 30,
},
{
id: 'build20',
label: 'Own 20 buildings total',
target: function () {
return 20;
},
progress: function () {
var total = 0;
for (var i = 0; i < Game.ObjectsById.length; i++) total += Game.ObjectsById[i].amount;
return total;
},
reward: 60,
},
];

var panel = document.createElement('div');
panel.id = 'nq-panel';
panel.className = 'inset title';
panel.innerHTML = [
'<div class="nq-header">Not Quite Lab</div>',
'<div id="nq-crumbs" class="nq-stat"></div>',
'<div id="nq-combo" class="nq-stat"></div>',
'<div id="nq-passive" class="nq-stat"></div>',
'<div class="nq-actions">',
'<button id="nq-burst" class="nq-btn">25 crumbs: Burst Batch</button>',
'<button id="nq-baker" class="nq-btn">100 crumbs: Recruit Street Baker</button>',
'</div>',
'<div id="nq-missions" class="nq-missions"></div>',
].join('');

var middle = document.getElementById('sectionMiddle');
var comments = document.getElementById('comments');
if (middle && comments) {
middle.insertBefore(panel, comments.nextSibling);
}

function spend(cost) {
if (state.crumbs < cost) {
Game.Notify('Not enough crumbs', 'You need ' + format(cost) + ' crumbs.', [16, 5]);
return false;
}
state.crumbs -= cost;
return true;
}

function earnCrumbs(amount) {
state.crumbs += amount;
state.lifetimeCrumbs += amount;
}

document.getElementById('nq-burst').addEventListener('click', function () {
if (!spend(25)) return;
var burst = Math.max(50, Game.cookiesPs * 30 + Game.computedMouseCps * 100);
Game.Earn(burst);
Game.Notify('Burst Batch!', '+' + format(burst) + ' cookies from a rogue recipe.', [0, 0]);
});

document.getElementById('nq-baker').addEventListener('click', function () {
if (!spend(100)) return;
state.passiveBakers += 1;
Game.Notify('Street Baker hired', 'Passive bakers now: ' + state.passiveBakers + '.', [1, 0]);
});

var bigCookie = document.getElementById('bigCookie');
if (bigCookie) {
bigCookie.addEventListener('click', function () {
var now = Date.now();
if (now - state.lastClickAt < 1200) {
state.combos += 1;
} else {
state.combos = 1;
}
state.lastClickAt = now;
state.bestCombo = Math.max(state.bestCombo, state.combos);

var bonus = Math.max(1, Math.floor(Game.computedMouseCps * 0.25 * state.combos));
Game.Earn(bonus);
earnCrumbs(1 + Math.floor(state.combos / 8));
});
}

function renderMissions() {
var lines = missions.map(function (mission) {
var progress = Math.min(mission.progress(), mission.target());
var done = !!state.fulfilledMissions[mission.id];
if (!done && progress >= mission.target()) {
state.fulfilledMissions[mission.id] = true;
earnCrumbs(mission.reward);
Game.Notify('Mission cleared!', mission.label + ' (+' + mission.reward + ' crumbs)', [11, 4]);
done = true;
}

return (
'<div class="nq-mission ' +
(done ? 'done' : '') +
'">' +
mission.label +
' - ' +
format(progress) +
'/' +
format(mission.target()) +
(done ? ' ✓' : '') +
'</div>'
);
});
document.getElementById('nq-missions').innerHTML = lines.join('');
}

function tick() {
var passiveGain = state.passiveBakers * Math.max(1, Game.computedMouseCps * 0.5);
if (passiveGain > 0) {
Game.Earn(passiveGain);
}

earnCrumbs(Math.max(0.2, Game.cookiesPs / 1200));
state.combos = Date.now() - state.lastClickAt > 1500 ? 0 : state.combos;

document.getElementById('nq-crumbs').textContent =
'Crumbs: ' + format(state.crumbs) + ' (lifetime ' + format(state.lifetimeCrumbs) + ')';
document.getElementById('nq-combo').textContent =
'Combo: x' + state.combos + ' (best x' + state.bestCombo + ')';
document.getElementById('nq-passive').textContent =
'Street bakers: ' + state.passiveBakers + ' (+' + format(passiveGain) + ' cookies/sec)';
renderMissions();
saveState(state);
}

tick();
setInterval(tick, 1000);
}

boot();
})();
54 changes: 53 additions & 1 deletion style.css
Original file line number Diff line number Diff line change
Expand Up @@ -1007,4 +1007,56 @@ a.control.middle{left:48px;top:48px;background-position:-48px -48px;}
.noFancy .price
{
text-shadow:0px 0px 4px #000,0px 1px 0px #000!important;
}
}
#nq-panel{
margin:6px 6px 0 6px;
padding:10px;
font-size:12px;
line-height:1.35em;
text-align:left;
background:linear-gradient(180deg,#30204d 0%,#1f1633 100%);
border:1px solid #7f5db9;
box-shadow:inset 0 0 8px rgba(255,255,255,0.12);
}

#nq-panel .nq-header{
font-size:18px;
color:#f8d7ff;
margin-bottom:6px;
}

#nq-panel .nq-stat{
color:#f4edff;
margin-bottom:4px;
}

#nq-panel .nq-actions{
display:flex;
flex-direction:column;
gap:4px;
margin:8px 0;
}

#nq-panel .nq-btn{
padding:6px 8px;
font-size:12px;
font-family:inherit;
cursor:pointer;
border:1px solid #9f78e0;
background:#4d3575;
color:#fff;
border-radius:4px;
}

#nq-panel .nq-btn:hover{
background:#69489c;
}

#nq-panel .nq-mission{
padding:2px 0;
color:#ded1ff;
}

#nq-panel .nq-mission.done{
color:#8cffae;
}