Added main tab for time experiments job

This commit is contained in:
thepaperpilot 2021-02-14 21:21:19 -06:00
parent c9ba4a7b49
commit 10d5bed127
12 changed files with 383 additions and 21 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 210 KiB

View file

@ -12,6 +12,7 @@
<script type="text/javascript" src="js/colors.js"></script>
<script type="text/javascript" src="js/Layers/flowers.js"></script>
<script type="text/javascript" src="js/Layers/study.js"></script>
<script type="text/javascript" src="js/Layers/sands.js"></script>
<script type="text/javascript" src="js/tree.js"></script>
<script type="text/javascript" src="js/mod.js"></script>
<script type="text/javascript" src="js/technical/temp.js"></script>

222
js/Layers/sands.js Normal file
View file

@ -0,0 +1,222 @@
function nextStoneCost() {
return new Decimal(100).times(new Decimal(1.1).pow(player.sands.stonesChipped));
}
addLayer("sands", {
name: "sands",
resource: "potentia",
image: "images/pexels-photo-1095601.jpeg",
color: sandsColor,
jobName: "Experiments with time",
showJobDelay: 0.5,
layerShown: () => player.chapter > 1 && hasMilestone("study", 2),
startData() {
return {
unlocked: false,
points: new Decimal(1),
xp: new Decimal(1),
lastLevel: new Decimal(1),
timeLoopActive: false,
grainsRemaining: new Decimal(0),
grainsFallen: new Decimal(0),
shrunkAmount: new Decimal(0),
chipping: false,
flipping: false,
stonesChipped: new Decimal(0),
fallTime: new Decimal(0),
flipTime: new Decimal(0)
};
},
getResetGain() {
if (!tmp[this.layer].layerShown || (player.tab !== this.layer && !player[this.layer].timeLoopActive)) {
return new Decimal(0);
}
let gain = new Decimal(1);
gain = gain.times(new Decimal(1.1).pow(getJobLevel(this.layer)));
return gain;
},
tabFormat: {
"Main": {
content: () => {
const percentChipped = new Decimal(1).sub(player.sands.shrunkAmount.div(nextStoneCost())).times(10000);
return [
"main-display",
"blank",
["display-text", (() => {
if (!hasMilestone("sands", 0)) {
return "Discover new ways to experiment at level 2";
}
if (!hasMilestone("sands", 1)) {
return "Discover new ways to experiment at level 4";
}
if (!hasMilestone("sands", 3)) {
return "Discover new ways to experiment at level 6";
}
if (!hasMilestone("sands", 4)) {
return "Discover new ways to experiment at level 8";
}
return "";
})()],
"blank",
["display-text", `Zoom Level: 1 / ${format(nextStoneCost().div(100))}x`],
"blank",
["display-text", `<div class="chipping-container">${new Array(100).fill(1).reduce((acc,_,i) => {
const singleSquarePercentChipped = percentChipped.sub(i * 100).clamp(0, 100);
const rowHeight = singleSquarePercentChipped.div(10).floor().times(10);
return acc + `<div class="chipping">
<div class="chipping-fill" style="height: ${rowHeight.toNumber()}%"></div>
<div class="chipping-fill" style="float: left; height: 10%; width: ${singleSquarePercentChipped.sub(rowHeight).times(10).toNumber()}%"></div>
</div>`;
}, "")}</div>`],
"blank",
["clickable", "chip"],
"blank",
"blank",
["display-text", formatWhole(player.sands.grainsRemaining)],
["display-text", `<div style="
--fill-duration: ${player.sands.flipping || player.sands.grainsRemaining.eq(0) ? 1 : player.sands.grainsRemaining.add(player.sands.grainsFallen).times(4).div(player.devSpeed).toNumber() + 0.05}s;
--fill-delay: -${player.sands.flipping || player.sands.grainsRemaining.eq(0) ? .999 : player.sands.grainsFallen.times(4).div(player.devSpeed).toNumber()}s;
--fill-state: ${player.sands.grainsRemaining.eq(0) || player.sands.flipping ? "paused" : "running"};
--flip-duration: ${new Decimal(5).div(player.devSpeed).toNumber() + 0.05}s;
--flip-state: ${player.sands.flipping ? "running" : "paused"};
"><div class="hourglass"></div></div>`],
["display-text", formatWhole(player.sands.grainsFallen)],
"blank",
["clickable", "flip"],
"blank",
"blank",
["milestones-filtered", [2, 5, 6]]
];
}
},
"Upgrades": {
content: () => [
"main-display",
"blank",
],
unlocked: () => hasMilestone("sands", 0)
}
},
update(diff) {
if (player.tab === this.layer || player[this.layer].timeLoopActive) {
if (player[this.layer].chipping) {
let shrinkGain = new Decimal(diff);
player[this.layer].shrunkAmount = player[this.layer].shrunkAmount.add(shrinkGain);
}
// https://gameanalytics.com/blog/idle-game-mathematics/
// b = 100
// r = 1.1
let grainsGain = player[this.layer].shrunkAmount.times(new Decimal(1.1).sub(1)).div(nextStoneCost()).add(1).log(1.1).floor();
if (grainsGain.gt(0)) {
player[this.layer].shrunkAmount = player[this.layer].shrunkAmount.sub(nextStoneCost().times(new Decimal(1.1).pow(grainsGain).sub(1)).div(new Decimal(1.1).sub(1)));
player[this.layer].stonesChipped = player[this.layer].stonesChipped.add(grainsGain);
// TODO grains gain modifiers go here. Make function to calculate so it can also be used when flipping
player[this.layer].grainsRemaining = player[this.layer].grainsRemaining.add(grainsGain);
}
if (player[this.layer].flipping) {
player[this.layer].fallTime = new Decimal(0);
player[this.layer].flipTime = player[this.layer].flipTime.add(diff);
const flipDuration = new Decimal(5);
if (player[this.layer].flipTime.gt(flipDuration)) {
player[this.layer].flipping = false;
player[this.layer].flipTime = new Decimal(0);
// TODO re-calculate number of grains from upgrades
player[this.layer].grainsRemaining = player[this.layer].grainsRemaining.add(player[this.layer].grainsFallen);
player[this.layer].grainsFallen = new Decimal(0);
}
} else {
player[this.layer].flipTime = new Decimal(0);
if (player[this.layer].grainsRemaining.gt(0)) {
player[this.layer].fallTime = player[this.layer].fallTime.add(diff);
const fallDuration = new Decimal(4);
const fallenGrains = player[this.layer].fallTime.div(fallDuration).floor().clampMax(player[this.layer].grainsRemaining);
if (fallenGrains.gt(0)) {
addPoints(this.layer, fallenGrains);
player[this.layer].grainsRemaining = player[this.layer].grainsRemaining.sub(fallenGrains);
player[this.layer].grainsFallen = player[this.layer].grainsFallen.add(fallenGrains);
if (fallenGrains.eq(player[this.layer].grainsRemaining)) {
player[this.layer].fallTime = new Decimal(0);
} else {
player[this.layer].fallTime = player[this.layer].fallTime.sub(fallenGrains.times(fallDuration));
}
}
} else {
player[this.layer].fallTime = new Decimal(0);
}
}
}
let jobLevel = new Decimal(getJobLevel(this.layer));
if (jobLevel.neq(player[this.layer].lastLevel) && player[this.layer].lastLevel.lte(100)) {
doPopup("none", `Level ${formatWhole(jobLevel)}`, "Level Up!", 3, layers[this.layer].color);
player[this.layer].lastLevel = jobLevel;
}
},
onAddPoints(gain) {
let xpGain = gain;
player[this.layer].xp = player[this.layer].xp.add(xpGain);
},
milestones: {
0: {
requirementDescription: "Level 2",
done: () => player.sands.xp.gte(10)
},
1: {
requirementDescription: "Level 4",
done: () => player.sands.xp.gte(1e3)
},
2: {
title: "I don't even know what I'm doing.",
requirementDescription: "Level 5",
"effectDescription": "Unlock a new time slot",
done: () => player.sands.xp.gte(1e4),
onComplete: () => {
player.timeSlots = player.timeSlots.add(1);
}
},
3: {
requirementDescription: "Level 6",
done: () => player.sands.xp.gte(1e5)
},
4: {
requirementDescription: "Level 8",
done: () => player.sands.xp.gte(1e7)
},
5: {
title: "I mean, this stuff is way too advanced for me.",
requirementDescription: "Level 10",
"effectDescription": "Unlock ??? job",
done: () => player.sands.xp.gte(1e9),
unlocked: () => hasMilestone("sands", 2)
},
6: {
title: "And what if I can't fix this? What are we gonna do?",
requirementDescription: "Level 25",
"effectDescription": "Unlock ???",
done: () => player.sands.xp.gte(1e24),
unlocked: () => hasMilestone("sands", 5)
}
},
clickables: {
chip: {
title: "Keep Moving Forward<br/>",
display: "Hold down the mouse to chip away at the stone until its the size of a grain of sand.",
touchstart: () => {
player.sands.chipping = true;
},
touchend: () => {
player.sands.chipping = false;
}
},
flip: {
title: "But he doesn't give up!",
display: "Flip the hourglass",
canClick: () => player.sands.grainsFallen.gt(0) && !player.sands.flipping,
onClick: () => {
player.sands.flipping = true;
}
}
}
});

View file

@ -135,13 +135,12 @@ addLayer("study", {
layerShown: () => player.chapter > 1 && hasMilestone("flowers", 4),
startData() {
return {
unlocked: true,
unlocked: false,
points: new Decimal(0),
insights: new Decimal(0),
total: new Decimal(0),
xp: new Decimal(0),
lastLevel: new Decimal(0),
realTime: 0,
timeLoopActive: false,
drawProgress: 0,
refreshProgress: 0,
@ -236,7 +235,6 @@ addLayer("study", {
},
update(diff) {
if (player.tab === this.layer || player[this.layer].timeLoopActive) {
player[this.layer].realTime += diff;
player[this.layer].drawProgress += diff;
if (player[this.layer].drawProgress > DRAW_PERIOD) {
player[this.layer].drawProgress = 0;
@ -291,7 +289,7 @@ addLayer("study", {
2: {
title: "And all dared to brave unknown terrors, to do mighty deeds,",
requirementDescription: "Level 5",
"effectDescription": "Unlock ??? job",
"effectDescription": "Unlock time experiments job",
done: () => player.study.xp.gte(1e4)
},
3: {
@ -363,3 +361,7 @@ addLayer("study", {
sellDiscount: getCardUpgradeBuyable("sellDiscount")
}
});
// Names references:
// https://www.shmoop.com/study-guides/literature/hitchhikers-guide-to-the-galaxy/quotes
// https://en.wikiquote.org/wiki/The_Hitchhiker's_Guide_to_the_Galaxy

View file

@ -4,3 +4,4 @@ const logoHighlightColor = "#000080";
const backgroundColor = "#2a323d";
const flowersColor = "#F1EBD9";
const studyColor = "#654321";
const sandsColor = "#C2B280";

View file

@ -317,14 +317,31 @@ function loadVue() {
props: ["layer", "data", "size"],
template: `
<button
v-if="tmp[layer].clickables && tmp[layer].clickables[data]!== undefined && tmp[layer].clickables[data].unlocked"
v-bind:class="{ upg: true, can: tmp[layer].clickables[data].canClick, locked: !tmp[layer].clickables[data].canClick}"
v-bind:style="[tmp[layer].clickables[data].canClick ? {'background-color': tmp[layer].color} : {}, size ? {'height': size, 'width': size} : {}, tmp[layer].clickables[data].style]"
v-on:click="clickClickable(layer, data)">
v-if="tmp[layer].clickables && tmp[layer].clickables[data]!== undefined && tmp[layer].clickables[data].unlocked !== false"
v-bind:class="{ upg: true, can: tmp[layer].clickables[data].canClick !== false, locked: tmp[layer].clickables[data].canClick === false}"
v-bind:style="[tmp[layer].clickables[data].canClick !== false ? {'background-color': tmp[layer].color} : {}, size ? {'height': size, 'width': size} : {}, tmp[layer].clickables[data].style]"
v-on="handlers">
<span v-if= "tmp[layer].clickables[data].title"><h2 v-html="tmp[layer].clickables[data].title"></h2><br></span>
<span v-bind:style="{'white-space': 'pre-line'}" v-html="tmp[layer].clickables[data].display"></span>
</button>
`
`,
data() {
const { layer, data } = this;
const handlers = {
click: () => clickClickable(layer, data),
mousedown: layers[layer].clickables[data].touchstart,
touchstart: layers[layer].clickables[data].touchstart,
mouseup: layers[layer].clickables[data].touchend,
touchend: layers[layer].clickables[data].touchend,
mouseleave: layers[layer].clickables[data].touchend
};
for (cb in handlers) {
if (handlers[cb] == null) {
delete handlers[cb];
}
}
return { handlers };
}
});
Vue.component("master-button", {
@ -360,7 +377,7 @@ function loadVue() {
Vue.component("bar", {
props: ["layer", "data"],
template: `
<div v-if="tmp[layer].bars && tmp[layer].bars[data].unlocked" v-bind:style="{'position': 'relative'}"><div v-bind:style="[tmp[layer].bars[data].style, tmp[layer].bars[data].dims, {'display': 'table', 'borderRadius': '10px', 'boxShadow': '0 0 10px 2px var(--shadowColor), inset 0 0 10px 4px var(--innerShadowColor)'}]">
<div v-if="tmp[layer].bars && tmp[layer].bars[data].unlocked !== false" v-bind:style="{'position': 'relative'}"><div v-bind:style="[tmp[layer].bars[data].style, tmp[layer].bars[data].dims, {'display': 'table', 'borderRadius': '10px', 'boxShadow': '0 0 10px 2px var(--shadowColor), inset 0 0 10px 4px var(--innerShadowColor)'}]">
<div class = "overlayTextContainer barBorder" v-bind:style="[tmp[layer].bars[data].borderStyle, tmp[layer].bars[data].dims]">
<span class = "overlayText" v-bind:style="[tmp[layer].bars[data].style, tmp[layer].bars[data].textStyle]" v-html="tmp[layer].bars[data].display"></span>
</div>

View file

@ -403,9 +403,6 @@ function gameLoop(diff) {
diff = 0;
player.tab = "gameEnded";
}
if (player.devSpeed) {
diff *= player.devSpeed;
}
if (maxTickLength) {
let limit = maxTickLength();

View file

@ -13,7 +13,7 @@ let modInfo = {
// Set your version in num and name
let VERSION = {
num: "0.13",
name: "Chapter 2",
name: "Chapter 2 (Time Experiments)",
};
let changelog = `<h1>Changelog:</h1><br>
@ -31,7 +31,7 @@ let winText = "Congratulations! You have reached the end and beaten this game, b
// If you add new functions anywhere inside of a layer, and those functions have an effect when called, add them here.
// (The ones here are examples, all official functions are already taken care of)
var doNotCallTheseFunctionsEveryTick = ["onAddPoints"];
var doNotCallTheseFunctionsEveryTick = ["onAddPoints", "touchstart", "touchend"];
function getStartPoints(){
return new Decimal(modInfo.initialStartPoints);

View file

@ -120,6 +120,8 @@ var systemComponents = {
The Prestige Tree made by Jacorb and Aarex
<br>
Original idea by papyrus (on discord)
<br>
Hourglass used with modifications from <a v-bind:href="'https://codepen.io/jkantner/pen/wvWXyKG'" target="_blank" class="link" v-bind:style = "{'font-size': '14px', 'display': 'inline'}" >jkantner</a> under MIT license
<br><br>
<div class="link" onclick="showTab('changelog-tab')">Changelog</div><br>
<span v-if="modInfo.discordLink"><a class="link" v-bind:href="modInfo.discordLink" target="_blank">{{modInfo.discordName}}</a><br></span>

View file

@ -42,7 +42,6 @@ function getJobProgressBar(job) {
let progress = player[job].xp.clampMin(1).sub(previousLevelRequirement).div(level.pow10().sub(previousLevelRequirement));
return progress;
},
unlocked: true,
fillStyle: { backgroundColor: layers[job].color },
borderStyle: { borderColor: layers[job].color }
};
@ -61,7 +60,8 @@ function toggleTimeLoop(layer) {
addLayer("tree-tab", {
bars: {
flowers: getJobProgressBar("flowers"),
study: getJobProgressBar("study")
study: getJobProgressBar("study"),
sands: getJobProgressBar("sands")
},
tabFormat: () => player.chapter < 3 ?
[
@ -73,7 +73,8 @@ addLayer("tree-tab", {
player.chapter === 2 ? ["display-text", `You have <span style="color: white; text-shadow: white 0 0 10px">${formatWhole(player.timeSlots.sub(player.usedTimeSlots))}</span> free time slots`] : null,
player.chapter === 2 ? "blank" : null,
["job", "flowers"],
["job", "study"]
["job", "study"],
["job", "sands"]
] :
{
"Main": {
@ -84,7 +85,8 @@ addLayer("tree-tab", {
"blank",
"blank",
["job", "flowers"],
["job", "study"]
["job", "study"],
["job", "sands"]
]
}
},

View file

@ -197,10 +197,10 @@ function clickClickable(layer, id) {
if (!player[layer].unlocked) {
return;
}
if (!tmp[layer].clickables[id].unlocked) {
if (tmp[layer].clickables[id].unlocked === false) {
return;
}
if (!tmp[layer].clickables[id].canClick) {
if (tmp[layer].clickables[id].canClick === false) {
return;
}
@ -364,6 +364,9 @@ function updateMilestones(layer) {
for (id in layers[layer].milestones) {
if (!(hasMilestone(layer, id)) && layers[layer].milestones[id].done()) {
player[layer].milestones.push(id);
if (isFunction(layers[layer].milestones[id].onComplete)) {
layers[layer].milestones[id].onComplete();
}
if (tmp[layer].milestonePopups || tmp[layer].milestonePopups === undefined) {
doPopup("milestone", tmp[layer].milestones[id].requirementDescription, "Milestone Gotten!", 3, tmp[layer].color);
}

115
style.css
View file

@ -799,3 +799,118 @@ button > * {
.cursor {
cursor: pointer;
}
.chipping-container {
display: flex;
flex-flow: row wrap;
width: 400px;
justify-content: space-around;
}
.chipping {
width: 30px;
height: 30px;
background: grey;
margin: 4px;
}
.chipping-fill {
background: white;
}
.hourglass {
--polygonH: polygon(0% 0%,100% 0%,100% 5.55%,95% 5.55%,95% 28%,60% 46%,60% 54%,95% 72%,95% 94.45%,100% 94.45%,100% 100%,0% 100%,0% 94.45%,5% 94.45%,5% 72%,40% 54%,40% 46%,5% 28%,5% 5.55%,0% 5.55%);
animation-name: flip;
animation-duration: var(--flip-duration);
animation-delay: 0;
animation-play-state: var(--flip-state);
animation-timing-function: ease-in-out;
background-image: linear-gradient(#C2B280 0.5em,#737a8c55 0.5em 8.5em,#C2B280 8.5em);
clip-path: var(--polygonH);
-webkit-clip-path: var(--polygonH);
overflow: hidden;
position: relative;
width: 5em;
height: 9em;
z-index: 0;
}
.hourglass:before, .hourglass:after {
animation-timing-function: linear;
content: "";
display: block;
position: absolute;
}
.hourglass:before {
--polygonB1: polygon(0% 0%,100% 0%,100% 24%,50% 47%,50% 47%,50% 47%,50% 47%,50% 47%,50% 47%,50% 47%,50% 47%,0% 24%);
--polygonB2: polygon(0% 4%,100% 4%,100% 24%,55% 45%,55% 100%,55% 100%,55% 100%,45% 100%,45% 100%,45% 100%,45% 45%,0% 24%);
--polygonB3: polygon(0% 24%,100% 24%,100% 24%,55% 45%,55% 80%,100% 100%,100% 100%,0% 100%,0% 100%,45% 80%,45% 45%,0% 24%);
--polygonB4: polygon(45% 45%,55% 45%,55% 45%,55% 45%,55% 58%,100% 76%,100% 100%,0% 100%,0% 76%,45% 58%,45% 45%,45% 45%);
--polygonB5: polygon(50% 53%,50% 53%,50% 53%,50% 53%,50% 53%,100% 76%,100% 100%,0% 100%,0% 76%,50% 53%,50% 53%,50% 53%);
animation-name: fill;
animation-duration: var(--fill-duration);
animation-delay: var(--fill-delay);
animation-play-state: var(--fill-state);
background-color: white;
background-size: 100% 3.6em;
clip-path: var(--polygonB1);
-webkit-clip-path: var(--polygonB1);
top: 0.5em;
left: 0.5em;
width: 4em;
height: 8em;
z-index: 1;
}
.hourglass:after {
animation-name: glare;
animation-duration: var(--flip-duration);
animation-delay: 0;
animation-play-state: var(--flip-state);
background:
linear-gradient(90deg,#0000 0.5em,#0003 0.5em 1.5em,#0000 1.5em 3.5em,#fff3 3.5em 4.5em,#fff0 4.5em 6.5em,#0003 6.5em 7.5em,#0000 7.5em) 0 0 / 100% 0.5em,
linear-gradient(90deg,#0000 0.75em,#0003 0.75em 1.25em,#0000 1.25em 3.75em,#fff3 3.75em 4.25em,#fff0 4.25em 6.75em,#0003 6.75em 7.25em,#0000 7.25em) 0 0.5em / 100% 8em,
linear-gradient(90deg,#0000 0.5em,#0003 0.5em 1.5em,#0000 1.5em 3.5em,#fff3 3.5em 4.5em,#fff0 4.5em 6.5em,#0003 6.5em 7.5em,#0000 7.5em) 0 100% / 100% 0.5em;
background-repeat: repeat-x;
top: 0;
left: -3em;
width: 200%;
height: 100%;
z-index: 2;
}
@keyframes fill {
from {
clip-path: var(--polygonB1);
-webkit-clip-path: var(--polygonB1);
}
15% {
clip-path: var(--polygonB2);
-webkit-clip-path: var(--polygonB2);
}
55% {
clip-path: var(--polygonB3);
-webkit-clip-path: var(--polygonB3);
}
95% {
clip-path: var(--polygonB4);
-webkit-clip-path: var(--polygonB4);
}
to {
clip-path: var(--polygonB5);
-webkit-clip-path: var(--polygonB5);
}
}
@keyframes glare {
from {
transform: translateX(0);
}
to {
transform: translateX(3em);
}
}
@keyframes flip {
from {
transform: rotate(0);
}
to {
transform: rotate(180deg);
}
}