mirror of
https://github.com/thepaperpilot/Advent-Incremental.git
synced 2024-11-24 17:31:54 +00:00
Implemented focus mechanic
This commit is contained in:
parent
b7b40a48aa
commit
0ce3b6b131
2 changed files with 128 additions and 6 deletions
|
@ -13,12 +13,13 @@ import { jsx } from "features/feature";
|
||||||
import { createHotkey, GenericHotkey } from "features/hotkey";
|
import { createHotkey, GenericHotkey } from "features/hotkey";
|
||||||
import { globalBus } from "game/events";
|
import { globalBus } from "game/events";
|
||||||
import { BaseLayer, createLayer } from "game/layers";
|
import { BaseLayer, createLayer } from "game/layers";
|
||||||
import { createMultiplicativeModifier } from "game/modifiers";
|
import { createMultiplicativeModifier, createSequentialModifier } from "game/modifiers";
|
||||||
import { persistent } from "game/persistence";
|
import { persistent } from "game/persistence";
|
||||||
import Decimal, { DecimalSource, format, formatWhole } from "util/bignum";
|
import Decimal, { DecimalSource, format, formatTime, formatWhole } from "util/bignum";
|
||||||
import { Direction } from "util/common";
|
import { Direction } from "util/common";
|
||||||
import { render, renderGrid } from "util/vue";
|
import { render, renderGrid } from "util/vue";
|
||||||
import { computed, ref, unref, watchEffect } from "vue";
|
import { computed, ref, unref, watchEffect } from "vue";
|
||||||
|
import "./styles/reindeer.css";
|
||||||
|
|
||||||
const id = "reindeer";
|
const id = "reindeer";
|
||||||
const day = 21;
|
const day = 21;
|
||||||
|
@ -28,7 +29,82 @@ const layer = createLayer(id, function (this: BaseLayer) {
|
||||||
|
|
||||||
const feedGoal = 1e3;
|
const feedGoal = 1e3;
|
||||||
|
|
||||||
// TODO focus
|
const currMultiplier = persistent<DecimalSource>(1);
|
||||||
|
const currTargets = persistent<Record<string, boolean>>({});
|
||||||
|
const currCooldown = persistent<number>(0);
|
||||||
|
|
||||||
|
const maxMultiplier = createSequentialModifier(() => []);
|
||||||
|
const computedMaxMultiplier = computed(() => maxMultiplier.apply(2));
|
||||||
|
const targetsCount = createSequentialModifier(() => []);
|
||||||
|
const computedTargetsCount = computed(() => targetsCount.apply(1));
|
||||||
|
const computedMaxCooldown = computed(() => 10);
|
||||||
|
|
||||||
|
const focusMeter = createBar(() => ({
|
||||||
|
direction: Direction.Right,
|
||||||
|
width: 476,
|
||||||
|
height: 50,
|
||||||
|
style: `border-radius: 0`,
|
||||||
|
borderStyle: `border-radius: 0`,
|
||||||
|
fillStyle: () => ({
|
||||||
|
background: currCooldown.value > 0 ? color : "#7f7f00",
|
||||||
|
animation: currCooldown.value > 0 ? "1s focused-eating-bar linear infinite" : "",
|
||||||
|
opacity: currCooldown.value > 0 ? currCooldown.value / 10 : 1,
|
||||||
|
transition: "none"
|
||||||
|
}),
|
||||||
|
progress: () =>
|
||||||
|
Decimal.sub(currMultiplier.value, 1)
|
||||||
|
.div(Decimal.sub(computedMaxMultiplier.value, 1))
|
||||||
|
.toNumber(),
|
||||||
|
display: jsx(() => (
|
||||||
|
<>
|
||||||
|
{format(currMultiplier.value)}x
|
||||||
|
{currCooldown.value > 0 ? (
|
||||||
|
<>
|
||||||
|
{" "}
|
||||||
|
to {Object.keys(currTargets.value).join(", ")} for{" "}
|
||||||
|
{formatTime(currCooldown.value)}
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
""
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
))
|
||||||
|
})) as GenericBar;
|
||||||
|
|
||||||
|
const focusButton = createClickable(() => ({
|
||||||
|
display: {
|
||||||
|
title: "Focus",
|
||||||
|
description: jsx(() => (
|
||||||
|
<>
|
||||||
|
Motivate reindeer to eat, multiplying {formatWhole(computedTargetsCount.value)}{" "}
|
||||||
|
random reindeer's eating rate by up to {format(computedMaxMultiplier.value)}x
|
||||||
|
for {formatTime(computedMaxCooldown.value)}, equal to the focus bar's effect.
|
||||||
|
</>
|
||||||
|
))
|
||||||
|
},
|
||||||
|
style: {
|
||||||
|
width: "480px",
|
||||||
|
minHeight: "80px",
|
||||||
|
zIndex: 4
|
||||||
|
},
|
||||||
|
canClick: () => Decimal.eq(currCooldown.value, 0),
|
||||||
|
onClick() {
|
||||||
|
currCooldown.value = Decimal.fromValue(computedMaxCooldown.value).toNumber();
|
||||||
|
let targetsSelected = 0;
|
||||||
|
currTargets.value = {};
|
||||||
|
while (Decimal.gt(computedTargetsCount.value, targetsSelected)) {
|
||||||
|
const selectedReindeer =
|
||||||
|
Object.values(reindeer)[
|
||||||
|
Math.floor(Math.random() * Object.values(reindeer).length)
|
||||||
|
];
|
||||||
|
const roll = selectedReindeer?.name ?? "";
|
||||||
|
if (!currTargets.value[roll]) {
|
||||||
|
currTargets.value[roll] = true;
|
||||||
|
targetsSelected++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
function createReindeer(options: {
|
function createReindeer(options: {
|
||||||
name: string;
|
name: string;
|
||||||
|
@ -56,7 +132,15 @@ const layer = createLayer(id, function (this: BaseLayer) {
|
||||||
style: "margin-top: 8px",
|
style: "margin-top: 8px",
|
||||||
borderStyle: "border-color: black",
|
borderStyle: "border-color: black",
|
||||||
baseStyle: "margin-top: -1px",
|
baseStyle: "margin-top: -1px",
|
||||||
fillStyle: "margin-top: -1px; transition-duration: 0s; background: black",
|
fillStyle: () => ({
|
||||||
|
marginTop: "-1px",
|
||||||
|
transitionDuration: "0s",
|
||||||
|
background: "black",
|
||||||
|
animation:
|
||||||
|
currTargets.value[options.name] && currCooldown.value > 0
|
||||||
|
? ".5s focused-eating-bar linear infinite"
|
||||||
|
: ""
|
||||||
|
}),
|
||||||
progress: () => Decimal.div(progress.value, computedCooldown.value)
|
progress: () => Decimal.div(progress.value, computedCooldown.value)
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -114,7 +198,11 @@ const layer = createLayer(id, function (this: BaseLayer) {
|
||||||
if (Decimal.gte(progress.value, computedCooldown.value)) {
|
if (Decimal.gte(progress.value, computedCooldown.value)) {
|
||||||
progress.value = computedCooldown.value;
|
progress.value = computedCooldown.value;
|
||||||
} else {
|
} else {
|
||||||
progress.value = Decimal.add(progress.value, diff);
|
let amount: DecimalSource = diff;
|
||||||
|
if (currTargets.value[options.name] && currCooldown.value > 0) {
|
||||||
|
amount = Decimal.times(amount, currMultiplier.value);
|
||||||
|
}
|
||||||
|
progress.value = Decimal.add(progress.value, amount);
|
||||||
if (clickable.isHolding.value) {
|
if (clickable.isHolding.value) {
|
||||||
clickable.onClick();
|
clickable.onClick();
|
||||||
}
|
}
|
||||||
|
@ -188,7 +276,18 @@ const layer = createLayer(id, function (this: BaseLayer) {
|
||||||
|
|
||||||
// TODO upgrades
|
// TODO upgrades
|
||||||
|
|
||||||
const [generalTab, generalTabCollapsed] = createCollapsibleModifierSections(() => []);
|
const [generalTab, generalTabCollapsed] = createCollapsibleModifierSections(() => [
|
||||||
|
{
|
||||||
|
title: "Max Focus Multiplier",
|
||||||
|
modifier: maxMultiplier,
|
||||||
|
base: 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Focus Targets",
|
||||||
|
modifier: targetsCount,
|
||||||
|
base: 1
|
||||||
|
}
|
||||||
|
]);
|
||||||
const showModifiersModal = ref(false);
|
const showModifiersModal = ref(false);
|
||||||
const modifiersModal = jsx(() => (
|
const modifiersModal = jsx(() => (
|
||||||
<Modal
|
<Modal
|
||||||
|
@ -207,6 +306,14 @@ const layer = createLayer(id, function (this: BaseLayer) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Object.values(reindeer).forEach(reindeer => reindeer.update(diff));
|
Object.values(reindeer).forEach(reindeer => reindeer.update(diff));
|
||||||
|
|
||||||
|
currCooldown.value = Math.max(currCooldown.value - diff, 0);
|
||||||
|
|
||||||
|
if (Decimal.eq(currCooldown.value, 0)) {
|
||||||
|
const speed = 1000;
|
||||||
|
const stoppedAt = 1 - Math.abs(Math.sin((Date.now() / speed) * 2));
|
||||||
|
currMultiplier.value = Decimal.pow(computedMaxMultiplier.value, stoppedAt);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const dayProgress = createBar(() => ({
|
const dayProgress = createBar(() => ({
|
||||||
|
@ -238,6 +345,9 @@ const layer = createLayer(id, function (this: BaseLayer) {
|
||||||
color,
|
color,
|
||||||
reindeer,
|
reindeer,
|
||||||
generalTabCollapsed,
|
generalTabCollapsed,
|
||||||
|
currMultiplier,
|
||||||
|
currTargets,
|
||||||
|
currCooldown,
|
||||||
minWidth: 700,
|
minWidth: 700,
|
||||||
display: jsx(() => (
|
display: jsx(() => (
|
||||||
<>
|
<>
|
||||||
|
@ -260,6 +370,8 @@ const layer = createLayer(id, function (this: BaseLayer) {
|
||||||
<div>You have fed reindeer {formatWhole(sumTimesFed.value)} times</div>
|
<div>You have fed reindeer {formatWhole(sumTimesFed.value)} times</div>
|
||||||
<Spacer />
|
<Spacer />
|
||||||
{renderGrid(
|
{renderGrid(
|
||||||
|
[focusButton],
|
||||||
|
[focusMeter],
|
||||||
[dasher, dancer, prancer],
|
[dasher, dancer, prancer],
|
||||||
[vixen, comet, cupid],
|
[vixen, comet, cupid],
|
||||||
[donner, blitzen, rudolph]
|
[donner, blitzen, rudolph]
|
||||||
|
|
10
src/data/layers/styles/reindeer.css
Normal file
10
src/data/layers/styles/reindeer.css
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
@keyframes focused-eating-bar {
|
||||||
|
from {
|
||||||
|
background: 0 0 / 28px 28px repeat
|
||||||
|
repeating-linear-gradient(-45deg, brown 0 10px, saddlebrown 10px 20px);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
background: 28px 0px / 28px 28px repeat
|
||||||
|
repeating-linear-gradient(-45deg, brown 0 10px, saddlebrown 10px 20px);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue