mirror of
https://github.com/thepaperpilot/Advent-Incremental.git
synced 2024-12-17 19:21:42 +00:00
Merge remote-tracking branch 'origin/main' into day-25-credits
This commit is contained in:
commit
944a7d717f
34 changed files with 1661 additions and 199 deletions
1
saves/Day 19 Complete.txt
Normal file
1
saves/Day 19 Complete.txt
Normal file
File diff suppressed because one or more lines are too long
1
saves/Day 20 Complete.txt
Normal file
1
saves/Day 20 Complete.txt
Normal file
File diff suppressed because one or more lines are too long
1
saves/Day 21 Complete.txt
Normal file
1
saves/Day 21 Complete.txt
Normal file
File diff suppressed because one or more lines are too long
|
@ -96,10 +96,9 @@ const useHeader = projInfo.useHeader;
|
|||
const loreBody = computeOptionalComponent(main.loreBody);
|
||||
|
||||
function gatherLayerProps(layer: GenericLayer) {
|
||||
const { display, minimized, minWidth, name, color, minimizable, nodes, minimizedDisplay } =
|
||||
layer;
|
||||
return { display, minimized, minWidth, name, color, minimizable, nodes, minimizedDisplay };
|
||||
};
|
||||
const { display, minimized, name, color, minimizable, nodes, minimizedDisplay } = layer;
|
||||
return { display, minimized, name, color, minimizable, nodes, minimizedDisplay };
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<div class="layer-container" :style="{ '--layer-color': unref(color) }">
|
||||
<button v-if="showGoBack" class="goBack" @click="goBack">❌</button>
|
||||
|
||||
<button class="layer-tab minimized" v-if="minimized" @click="setMinimized(false)">
|
||||
<button class="layer-tab minimized" v-if="unref(minimized)" @click="setMinimized(false)">
|
||||
<component v-if="minimizedComponent" :is="minimizedComponent" />
|
||||
<div v-else>{{ unref(name) }}</div>
|
||||
</button>
|
||||
|
@ -34,10 +34,6 @@ export default defineComponent({
|
|||
type: Number,
|
||||
required: true
|
||||
},
|
||||
tab: {
|
||||
type: Function as PropType<() => HTMLElement | undefined>,
|
||||
required: true
|
||||
},
|
||||
display: {
|
||||
type: processedPropType<CoercableComponent>(Object, String, Function),
|
||||
required: true
|
||||
|
@ -47,10 +43,6 @@ export default defineComponent({
|
|||
type: Object as PropType<Persistent<boolean>>,
|
||||
required: true
|
||||
},
|
||||
minWidth: {
|
||||
type: processedPropType<number | string>(Number, String),
|
||||
required: true
|
||||
},
|
||||
name: {
|
||||
type: processedPropType<string>(String),
|
||||
required: true
|
||||
|
@ -63,7 +55,7 @@ export default defineComponent({
|
|||
}
|
||||
},
|
||||
setup(props) {
|
||||
const { display, index, minimized, minWidth, tab, minimizedDisplay, name } = toRefs(props);
|
||||
const { display, index, minimized, minimizedDisplay } = toRefs(props);
|
||||
|
||||
const component = computeComponent(display);
|
||||
const minimizedComponent = computeOptionalComponent(minimizedDisplay);
|
||||
|
@ -79,39 +71,10 @@ export default defineComponent({
|
|||
minimized.value = min;
|
||||
}
|
||||
|
||||
nextTick(() => updateTab(minimized.value, unref(minWidth.value)));
|
||||
watch([name, minimized, wrapRef(minWidth)], ([name, minimized, minWidth]) => {
|
||||
updateTab(minimized, minWidth);
|
||||
});
|
||||
|
||||
function updateNodes(nodes: Record<string, FeatureNode | undefined>) {
|
||||
props.nodes.value = nodes;
|
||||
}
|
||||
|
||||
function updateTab(min: boolean, minWidth: number | string) {
|
||||
minimized.value = min;
|
||||
const width =
|
||||
typeof minWidth === "number" || Number.isNaN(parseInt(minWidth))
|
||||
? minWidth + "px"
|
||||
: minWidth;
|
||||
const tabValue = tab.value();
|
||||
if (tabValue != undefined) {
|
||||
if (min) {
|
||||
tabValue.style.flexGrow = "0";
|
||||
tabValue.style.flexShrink = "0";
|
||||
tabValue.style.width = "60px";
|
||||
tabValue.style.minWidth = tabValue.style.flexBasis = "";
|
||||
tabValue.style.margin = "0";
|
||||
} else {
|
||||
tabValue.style.flexGrow = "";
|
||||
tabValue.style.flexShrink = "";
|
||||
tabValue.style.width = "";
|
||||
tabValue.style.minWidth = tabValue.style.flexBasis = width;
|
||||
tabValue.style.margin = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
component,
|
||||
minimizedComponent,
|
||||
|
@ -119,16 +82,13 @@ export default defineComponent({
|
|||
updateNodes,
|
||||
unref,
|
||||
goBack,
|
||||
setMinimized,
|
||||
minimized,
|
||||
minWidth
|
||||
setMinimized
|
||||
};
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
.layer-tab:not(.minimized) {
|
||||
padding-top: 20px;
|
||||
padding-bottom: 20px;
|
||||
|
|
|
@ -98,7 +98,7 @@ const isPaused = computed({
|
|||
});
|
||||
|
||||
const canAutoSave = computed(
|
||||
() => (layers as any).main.days[(layers as any).main.day.value - 1].opened.value
|
||||
() => (layers as any).main?.days[(layers as any).main?.day.value - 1].opened.value
|
||||
);
|
||||
|
||||
const autosaveTitle = jsx(() => (
|
||||
|
|
|
@ -6,7 +6,13 @@
|
|||
class="scene-item"
|
||||
style="left: 4%; bottom: 3%; width: 40px; height: 40px"
|
||||
/>
|
||||
<img v-if="day >= 0" :src="tree" class="scene-item" style="left: 10%; bottom: 10%" />
|
||||
<img
|
||||
v-if="day >= 0"
|
||||
:src="tree"
|
||||
class="scene-item"
|
||||
style="left: 6%; bottom: 10%; width: 120px; height: 120px"
|
||||
/>
|
||||
<img v-if="day >= 20" :src="reindeer" class="scene-item" style="left: 13%; bottom: 8%" />
|
||||
<img
|
||||
v-if="day >= 13"
|
||||
:src="letters"
|
||||
|
@ -69,6 +75,7 @@
|
|||
<div v-if="day >= 4" class="scene-bubble left" style="left: 64%; bottom: 37%">
|
||||
<img v-if="day >= 17" :src="toys" class="scene-item" />
|
||||
<img v-if="day >= 18" :src="advFactory" class="scene-item" />
|
||||
<img v-if="day >= 19" :src="presents" class="scene-item" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -93,6 +100,8 @@ import ribbons from "./symbols/ribbons.png";
|
|||
import toys from "./symbols/truck.png";
|
||||
import factory from "./symbols/gears.png";
|
||||
import advFactory from "./symbols/teddyBear.png";
|
||||
import presents from "./symbols/presents.png";
|
||||
import reindeer from "./symbols/reindeer.png";
|
||||
|
||||
defineProps<{
|
||||
day: number;
|
||||
|
|
|
@ -28,9 +28,11 @@ import { render, renderGrid } from "util/vue";
|
|||
import { computed, ComputedRef, ref, unref } from "vue";
|
||||
import dyes from "./dyes";
|
||||
import elves, { ElfBuyable } from "./elves";
|
||||
import factory from "./factory";
|
||||
import management from "./management";
|
||||
import paper from "./paper";
|
||||
import plastic from "./plastic";
|
||||
import reindeer from "./reindeer";
|
||||
import trees from "./trees";
|
||||
import workshop from "./workshop";
|
||||
import wrappingPaper from "./wrapping-paper";
|
||||
|
@ -55,6 +57,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
|
|||
description: "1000% Foundation Completed",
|
||||
enabled: workshop.milestones.extraExpansionMilestone5.earned
|
||||
})),
|
||||
reindeer.reindeer.vixen.modifier,
|
||||
createExponentialModifier(() => ({
|
||||
exponent: 1.1,
|
||||
description: "Bell Level 2",
|
||||
|
@ -587,7 +590,36 @@ const layer = createLayer(id, function (this: BaseLayer) {
|
|||
Decimal.add(plasticBoxesBuyable.amount.value, plasticBoxesBuyable.freeLevels.value)
|
||||
)
|
||||
})) as BoxesBuyable;
|
||||
const presentBuyable = createBuyable(() => ({
|
||||
display: {
|
||||
title: "Carry presents in boxes",
|
||||
description: jsx(() => (
|
||||
<>
|
||||
Use boxes to carry presents, boosting its gain
|
||||
<br />
|
||||
<br />
|
||||
<div>Amount: {formatWhole(presentBuyable.amount.value)} boxes</div>
|
||||
</>
|
||||
)),
|
||||
effectDisplay: jsx(() => (
|
||||
<>{format(Decimal.div(presentBuyable.amount.value, 10).add(1).pow(2))}x</>
|
||||
)),
|
||||
showAmount: false
|
||||
},
|
||||
resource: noPersist(boxes),
|
||||
cost() {
|
||||
return Decimal.pow(2, presentBuyable.amount.value).mul(1e87);
|
||||
},
|
||||
inverseCost(x: DecimalSource) {
|
||||
const amt = Decimal.div(x, 1e87).log2();
|
||||
return Decimal.isNaN(amt) ? Decimal.dZero : amt.floor().max(0);
|
||||
},
|
||||
freeLevels: computed(() => 0),
|
||||
totalAmount: computed(() => presentBuyable.amount.value),
|
||||
visibility: () => showIf(factory.upgrades[3][3].bought.value)
|
||||
})) as BoxesBuyable;
|
||||
const buyables2 = { oreBoxesBuyable, metalBoxesBuyable, plasticBoxesBuyable };
|
||||
const buyables3 = { presentBuyable };
|
||||
globalBus.on("update", diff => {
|
||||
if (Decimal.lt(main.day.value, day)) {
|
||||
return;
|
||||
|
@ -677,6 +709,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
|
|||
row3Upgrades,
|
||||
buyables,
|
||||
buyables2,
|
||||
buyables3,
|
||||
minWidth: 700,
|
||||
generalTabCollapsed,
|
||||
display: jsx(() => (
|
||||
|
@ -703,7 +736,11 @@ const layer = createLayer(id, function (this: BaseLayer) {
|
|||
Object.values(row3Upgrades)
|
||||
)}
|
||||
<Spacer />
|
||||
{renderGrid(Object.values(buyables), Object.values(buyables2))}
|
||||
{renderGrid(
|
||||
Object.values(buyables),
|
||||
Object.values(buyables2),
|
||||
Object.values(buyables3)
|
||||
)}
|
||||
</>
|
||||
)),
|
||||
minimizedDisplay: jsx(() => (
|
||||
|
|
|
@ -21,12 +21,13 @@ import { BaseLayer, createLayer } from "game/layers";
|
|||
import {
|
||||
createAdditiveModifier,
|
||||
createMultiplicativeModifier,
|
||||
createSequentialModifier
|
||||
createSequentialModifier,
|
||||
Modifier
|
||||
} from "game/modifiers";
|
||||
import { noPersist, persistent } from "game/persistence";
|
||||
import Decimal, { DecimalSource, format } from "util/bignum";
|
||||
import { formatWhole } from "util/break_eternity";
|
||||
import { Direction } from "util/common";
|
||||
import { Direction, WithRequired } from "util/common";
|
||||
import { render, renderCol, renderRow } from "util/vue";
|
||||
import { computed, ref, unref } from "vue";
|
||||
import boxes from "./boxes";
|
||||
|
@ -36,6 +37,7 @@ import management from "./management";
|
|||
import metal from "./metal";
|
||||
import paper from "./paper";
|
||||
import plastic from "./plastic";
|
||||
import reindeer from "./reindeer";
|
||||
import trees from "./trees";
|
||||
import workshop from "./workshop";
|
||||
|
||||
|
@ -449,8 +451,9 @@ const layer = createLayer(id, function (this: BaseLayer) {
|
|||
multiplier: dyes.boosts.yellow2,
|
||||
description: "Yellow Dye",
|
||||
enabled: dyes.masteryEffectActive
|
||||
}))
|
||||
]);
|
||||
})),
|
||||
reindeer.reindeer.cupid.modifier
|
||||
]) as WithRequired<Modifier, "description" | "revert">;
|
||||
const computedSheepGain = computed(() => sheepGain.apply(1));
|
||||
const breedingCooldown = createSequentialModifier(() => []);
|
||||
const computedBreedingCooldown = computed(() => breedingCooldown.apply(1));
|
||||
|
@ -494,8 +497,9 @@ const layer = createLayer(id, function (this: BaseLayer) {
|
|||
multiplier: dyes.boosts.yellow2,
|
||||
description: "Yellow Dye",
|
||||
enabled: dyes.masteryEffectActive
|
||||
}))
|
||||
]);
|
||||
})),
|
||||
reindeer.reindeer.cupid.modifier
|
||||
]) as WithRequired<Modifier, "description" | "revert">;
|
||||
const computedShearingAmount = computed(() => shearingAmount.apply(1));
|
||||
const shearingCooldown = createSequentialModifier(() => []);
|
||||
const computedShearingCooldown = computed(() => shearingCooldown.apply(1));
|
||||
|
@ -539,8 +543,9 @@ const layer = createLayer(id, function (this: BaseLayer) {
|
|||
multiplier: dyes.boosts.yellow2,
|
||||
description: "Yellow Dye",
|
||||
enabled: dyes.masteryEffectActive
|
||||
}))
|
||||
]);
|
||||
})),
|
||||
reindeer.reindeer.cupid.modifier
|
||||
]) as WithRequired<Modifier, "description" | "revert">;
|
||||
const computedSpinningAmount = computed(() => spinningAmount.apply(1));
|
||||
const spinningCooldown = createSequentialModifier(() => []);
|
||||
const computedSpinningCooldown = computed(() => spinningCooldown.apply(1));
|
||||
|
|
|
@ -29,6 +29,7 @@ import {
|
|||
import { noPersist, persistent } from "game/persistence";
|
||||
import Decimal, { DecimalSource, format, formatWhole } from "util/bignum";
|
||||
import { WithRequired } from "util/common";
|
||||
import { Computable } from "util/computed";
|
||||
import { render, renderGrid, renderRow } from "util/vue";
|
||||
import { computed, ref, unref } from "vue";
|
||||
import boxes from "./boxes";
|
||||
|
@ -40,6 +41,7 @@ import metal from "./metal";
|
|||
import oil from "./oil";
|
||||
import paper from "./paper";
|
||||
import plastic from "./plastic";
|
||||
import reindeer from "./reindeer";
|
||||
import trees from "./trees";
|
||||
import wrappingPaper from "./wrapping-paper";
|
||||
|
||||
|
@ -47,7 +49,7 @@ interface BetterFertilizerUpgOptions {
|
|||
canAfford: () => boolean;
|
||||
onPurchase: VoidFunction;
|
||||
display: JSXFunction;
|
||||
style: StyleValue;
|
||||
style: Computable<StyleValue>;
|
||||
visibility: () => Visibility;
|
||||
}
|
||||
interface UnlockKilnUpgOptions {
|
||||
|
@ -57,7 +59,7 @@ interface UnlockKilnUpgOptions {
|
|||
title: string;
|
||||
description: string;
|
||||
};
|
||||
style: StyleValue;
|
||||
style: Computable<StyleValue>;
|
||||
visibility: () => Visibility;
|
||||
}
|
||||
interface EfficientSmeltherUpgOptions {
|
||||
|
@ -67,7 +69,7 @@ interface EfficientSmeltherUpgOptions {
|
|||
title: string;
|
||||
description: string;
|
||||
};
|
||||
style: StyleValue;
|
||||
style: Computable<StyleValue>;
|
||||
visibility: () => Visibility;
|
||||
}
|
||||
|
||||
|
@ -360,7 +362,9 @@ const layer = createLayer(id, function (this: BaseLayer) {
|
|||
title: "Warmer Cutters",
|
||||
description: "Cut down twice as many trees/s"
|
||||
},
|
||||
style: { color: colorText }
|
||||
style() {
|
||||
return this.bought.value ? "" : { color: colorText };
|
||||
}
|
||||
}));
|
||||
const warmerPlanters = createUpgrade(() => ({
|
||||
resource: noPersist(coal),
|
||||
|
@ -369,7 +373,9 @@ const layer = createLayer(id, function (this: BaseLayer) {
|
|||
title: "Warmer Planters",
|
||||
description: "Plant twice as many trees/s"
|
||||
},
|
||||
style: { color: colorText }
|
||||
style() {
|
||||
return this.bought.value ? "" : { color: colorText };
|
||||
}
|
||||
}));
|
||||
const basicFertilizer = createUpgrade(() => ({
|
||||
resource: noPersist(ash),
|
||||
|
@ -378,7 +384,9 @@ const layer = createLayer(id, function (this: BaseLayer) {
|
|||
title: "Ashy Soil",
|
||||
description: "Trees give 25% more logs"
|
||||
},
|
||||
style: { color: colorText }
|
||||
style() {
|
||||
return this.bought.value ? "" : { color: colorText };
|
||||
}
|
||||
}));
|
||||
const unlockBonfire = createUpgrade(() => ({
|
||||
resource: fireResource,
|
||||
|
@ -388,9 +396,11 @@ const layer = createLayer(id, function (this: BaseLayer) {
|
|||
description: "Put all those fires together into a larger blaze"
|
||||
},
|
||||
onPurchase() {
|
||||
fireResource.value = Decimal.add(fireResource.value, this.cost);
|
||||
fireResource.value = Decimal.add(fireResource.value, this.cost as number);
|
||||
},
|
||||
style: { color: colorText }
|
||||
style() {
|
||||
return this.bought.value ? "" : { color: colorText };
|
||||
}
|
||||
}));
|
||||
const row1upgrades = [warmerCutters, warmerPlanters, basicFertilizer, unlockBonfire];
|
||||
|
||||
|
@ -401,7 +411,9 @@ const layer = createLayer(id, function (this: BaseLayer) {
|
|||
title: "Dedicated Cutter Heaters",
|
||||
description: "Double the bonus from Heated Cutters"
|
||||
},
|
||||
style: { color: colorText },
|
||||
style() {
|
||||
return this.bought.value ? "" : { color: colorText };
|
||||
},
|
||||
visibility: () => showIf(unlockBonfire.bought.value)
|
||||
}));
|
||||
const dedicatedPlanters = createUpgrade(() => ({
|
||||
|
@ -411,7 +423,9 @@ const layer = createLayer(id, function (this: BaseLayer) {
|
|||
title: "Dedicated Planter Heaters",
|
||||
description: "Double the bonus from Heated Planters"
|
||||
},
|
||||
style: { color: colorText },
|
||||
style() {
|
||||
return this.bought.value ? "" : { color: colorText };
|
||||
},
|
||||
visibility: () => showIf(unlockBonfire.bought.value)
|
||||
}));
|
||||
const betterFertilizer: Upgrade<BetterFertilizerUpgOptions> = createUpgrade(() => ({
|
||||
|
@ -434,7 +448,9 @@ const layer = createLayer(id, function (this: BaseLayer) {
|
|||
{formatWhole(1e5)} {ash.displayName}
|
||||
</>
|
||||
)),
|
||||
style: { color: colorText },
|
||||
style() {
|
||||
return this.bought.value ? "" : { color: colorText };
|
||||
},
|
||||
visibility: () => showIf(unlockBonfire.bought.value)
|
||||
}));
|
||||
|
||||
|
@ -445,7 +461,9 @@ const layer = createLayer(id, function (this: BaseLayer) {
|
|||
title: "Efficient Fires",
|
||||
description: "Move the fires underground to keep the coal from turning to ash"
|
||||
},
|
||||
style: { color: colorText },
|
||||
style() {
|
||||
return this.bought.value ? "" : { color: colorText };
|
||||
},
|
||||
visibility: () => showIf(unlockBonfire.bought.value)
|
||||
}));
|
||||
const row2upgrades = [dedicatedCutters, dedicatedPlanters, betterFertilizer, unlockKiln];
|
||||
|
@ -457,7 +475,9 @@ const layer = createLayer(id, function (this: BaseLayer) {
|
|||
title: "Efficient Crucibles",
|
||||
description: "Double auto smelting speed and triple metal gain from auto smelting"
|
||||
},
|
||||
style: { color: colorText },
|
||||
style() {
|
||||
return this.bought.value ? "" : { color: colorText };
|
||||
},
|
||||
visibility: () => showIf(oil.depthMilestones[4].earned.value)
|
||||
}));
|
||||
const arsonistAssistance = createUpgrade(() => ({
|
||||
|
@ -467,7 +487,9 @@ const layer = createLayer(id, function (this: BaseLayer) {
|
|||
title: "Arsonist Assistance",
|
||||
description: "Every elf at or above level 5 doubles ash gain"
|
||||
},
|
||||
style: { color: colorText },
|
||||
style() {
|
||||
return this.bought.value ? "" : { color: colorText };
|
||||
},
|
||||
visibility: () =>
|
||||
showIf(management.elfTraining.coalDrillElfTraining.milestones[3].earned.value)
|
||||
}));
|
||||
|
@ -478,7 +500,9 @@ const layer = createLayer(id, function (this: BaseLayer) {
|
|||
title: "Refined Coal",
|
||||
description: "Refineries boost coal gain"
|
||||
},
|
||||
style: { color: colorText },
|
||||
style() {
|
||||
return this.bought.value ? "" : { color: colorText };
|
||||
},
|
||||
visibility: () =>
|
||||
showIf(management.elfTraining.coalDrillElfTraining.milestones[3].earned.value)
|
||||
}));
|
||||
|
@ -489,7 +513,9 @@ const layer = createLayer(id, function (this: BaseLayer) {
|
|||
title: "Colored Fire",
|
||||
description: "Green dye also affects small fire synergy"
|
||||
},
|
||||
style: { color: colorText },
|
||||
style() {
|
||||
return this.bought.value ? "" : { color: colorText };
|
||||
},
|
||||
visibility: () =>
|
||||
showIf(management.elfTraining.coalDrillElfTraining.milestones[3].earned.value)
|
||||
}));
|
||||
|
@ -785,6 +811,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
|
|||
description: "Refined Coal",
|
||||
enabled: refinedCoal.bought
|
||||
})),
|
||||
reindeer.reindeer.dancer.modifier,
|
||||
createExponentialModifier(() => ({
|
||||
exponent: 1.05,
|
||||
description: "Jack Level 2",
|
||||
|
|
|
@ -37,6 +37,7 @@ import paper from "./paper";
|
|||
import trees from "./trees";
|
||||
import toys from "./toys";
|
||||
import factory from "./factory";
|
||||
import reindeer from "./reindeer";
|
||||
|
||||
interface Dye {
|
||||
name: string;
|
||||
|
@ -201,6 +202,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
|
|||
enabled: boxes.row3Upgrades.dyeUpgrade.bought
|
||||
}))
|
||||
);
|
||||
modifiers.push(reindeer.reindeer.rudolph.modifier);
|
||||
return modifiers;
|
||||
}) as WithRequired<Modifier, "description" | "revert">;
|
||||
const computedToGenerate = computed(() => toGenerate.apply(0));
|
||||
|
|
|
@ -876,7 +876,11 @@ const layer = createLayer(id, function (this: BaseLayer) {
|
|||
name: "Bell",
|
||||
description:
|
||||
"Bell will automatically purchase all box buyables you can afford, without actually spending any boxes.",
|
||||
buyable: [...Object.values(boxes.buyables), ...Object.values(boxes.buyables2)],
|
||||
buyable: [
|
||||
...Object.values(boxes.buyables),
|
||||
...Object.values(boxes.buyables2),
|
||||
...Object.values(boxes.buyables3)
|
||||
],
|
||||
cooldownModifier: boxCooldown,
|
||||
visibility: () => showIf(plastic.elfUpgrades.boxElf.bought.value)
|
||||
});
|
||||
|
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
123
src/data/layers/factory-components/boxmaker.svg
Normal file
123
src/data/layers/factory-components/boxmaker.svg
Normal file
|
@ -0,0 +1,123 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="50"
|
||||
height="50"
|
||||
viewBox="0 0 13.229166 13.229167"
|
||||
version="1.1"
|
||||
id="svg5"
|
||||
sodipodi:docname="advent.svg"
|
||||
inkscape:version="1.2.1 (9c6d41e4, 2022-07-14)"
|
||||
inkscape:export-filename="advent/boxmaker.png"
|
||||
inkscape:export-xdpi="96"
|
||||
inkscape:export-ydpi="96"
|
||||
xml:space="preserve"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
|
||||
id="namedview7"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:document-units="mm"
|
||||
showgrid="false"
|
||||
inkscape:zoom="3.0909964"
|
||||
inkscape:cx="3.0734426"
|
||||
inkscape:cy="59.527731"
|
||||
inkscape:window-width="1309"
|
||||
inkscape:window-height="804"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="25"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="layer1" /><defs
|
||||
id="defs2" /><g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"><rect
|
||||
style="fill:#e6e6e6;fill-opacity:1;stroke:#838390;stroke-width:0.764057;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:6;stroke-dasharray:none;stroke-opacity:1;paint-order:markers stroke fill"
|
||||
id="rect28545-6"
|
||||
width="12.46511"
|
||||
height="12.46511"
|
||||
x="0.38202849"
|
||||
y="0.38202882"
|
||||
rx="1.246511" /><image
|
||||
width="11.600364"
|
||||
height="11.600364"
|
||||
preserveAspectRatio="none"
|
||||
xlink:href="data:image/png;base64,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
|
||||
"
|
||||
id="image727"
|
||||
x="0.74370372"
|
||||
y="0.35876995" /></g></svg>
|
After Width: | Height: | Size: 6.9 KiB |
File diff suppressed because it is too large
Load diff
|
@ -76,10 +76,9 @@ const layer = createLayer(id, function (this: BaseLayer) {
|
|||
if (Decimal.lt(processingProgress.value, computedProcessingCooldown.value)) {
|
||||
return;
|
||||
}
|
||||
const amount = Decimal.div(
|
||||
processingProgress.value,
|
||||
computedProcessingCooldown.value
|
||||
).floor();
|
||||
const amount = Decimal.div(processingProgress.value, computedProcessingCooldown.value)
|
||||
.floor()
|
||||
.max(1);
|
||||
letters.value = Decimal.times(amount, computedLettersGain.value)
|
||||
.add(letters.value)
|
||||
.min(8e9);
|
||||
|
|
|
@ -37,6 +37,7 @@ import plastic from "./plastic";
|
|||
import workshop from "./workshop";
|
||||
import wrappingPaper from "./wrapping-paper";
|
||||
import toys from "./toys";
|
||||
import reindeer from "./reindeer";
|
||||
|
||||
const id = "metal";
|
||||
const day = 7;
|
||||
|
@ -105,6 +106,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
|
|||
description: "Twinkle Level 1",
|
||||
enabled: management.elfTraining.metalElfTraining.milestones[0].earned
|
||||
})),
|
||||
reindeer.reindeer.comet.modifier,
|
||||
createExponentialModifier(() => ({
|
||||
exponent: 1.1,
|
||||
description: "Mary Level 2",
|
||||
|
|
|
@ -43,6 +43,7 @@ import { WithRequired } from "util/common";
|
|||
import { ElfBuyable } from "./elves";
|
||||
import toys from "./toys";
|
||||
import factory from "./factory";
|
||||
import reindeer from "./reindeer";
|
||||
|
||||
const id = "oil";
|
||||
const day = 9;
|
||||
|
@ -625,7 +626,9 @@ const layer = createLayer(id, function (this: BaseLayer) {
|
|||
description: "Increase drill power by +4% per Coal Drill owned.",
|
||||
effectDisplay: jsx(() => <>x{format(row1UpgradeEffects[0].value)}</>)
|
||||
},
|
||||
style: { color: colorText }
|
||||
style() {
|
||||
return this.bought.value ? "" : { color: colorText };
|
||||
}
|
||||
})),
|
||||
createUpgrade(() => ({
|
||||
resource: metal.metal,
|
||||
|
@ -635,7 +638,9 @@ const layer = createLayer(id, function (this: BaseLayer) {
|
|||
description: "Increase drill power by +4% per Metal Drill owned.",
|
||||
effectDisplay: jsx(() => <>x{format(row1UpgradeEffects[1].value)}</>)
|
||||
},
|
||||
style: { color: colorText }
|
||||
style() {
|
||||
return this.bought.value ? "" : { color: colorText };
|
||||
}
|
||||
})),
|
||||
createUpgrade(() => ({
|
||||
resource: coal.coal,
|
||||
|
@ -645,7 +650,9 @@ const layer = createLayer(id, function (this: BaseLayer) {
|
|||
description: "Increase drill power by +6% per OoM of coal owned.",
|
||||
effectDisplay: jsx(() => <>x{format(row1UpgradeEffects[2].value)}</>)
|
||||
},
|
||||
style: { color: colorText }
|
||||
style() {
|
||||
return this.bought.value ? "" : { color: colorText };
|
||||
}
|
||||
})),
|
||||
createUpgrade(() => ({
|
||||
resource: metal.metal,
|
||||
|
@ -655,7 +662,9 @@ const layer = createLayer(id, function (this: BaseLayer) {
|
|||
description: "Increase drill power by +10% per OoM of metal ingot owned.",
|
||||
effectDisplay: jsx(() => <>x{format(row1UpgradeEffects[3].value)}</>)
|
||||
},
|
||||
style: { color: colorText }
|
||||
style() {
|
||||
return this.bought.value ? "" : { color: colorText };
|
||||
}
|
||||
})),
|
||||
createUpgrade(() => ({
|
||||
resource: noPersist(oil),
|
||||
|
@ -667,7 +676,9 @@ const layer = createLayer(id, function (this: BaseLayer) {
|
|||
<>+{format(Decimal.mul(row1UpgradeEffects[4].value, 100))}%</>
|
||||
))
|
||||
},
|
||||
style: { color: colorText }
|
||||
style() {
|
||||
return this.bought.value ? "" : { color: colorText };
|
||||
}
|
||||
}))
|
||||
];
|
||||
const row1UpgradeEffects: ComputedRef<DecimalSource>[] = [
|
||||
|
@ -706,7 +717,9 @@ const layer = createLayer(id, function (this: BaseLayer) {
|
|||
title: "Oil the Oil Pump",
|
||||
description: "Double oil gain."
|
||||
},
|
||||
style: { color: colorText }
|
||||
style() {
|
||||
return this.bought.value ? "" : { color: colorText };
|
||||
}
|
||||
})),
|
||||
createUpgrade(() => ({
|
||||
resource: noPersist(oil),
|
||||
|
@ -716,7 +729,9 @@ const layer = createLayer(id, function (this: BaseLayer) {
|
|||
description:
|
||||
"Double ore mining speed and square the coal drill amount in its effect."
|
||||
},
|
||||
style: { color: colorText }
|
||||
style() {
|
||||
return this.bought.value ? "" : { color: colorText };
|
||||
}
|
||||
})),
|
||||
createUpgrade(() => ({
|
||||
resource: noPersist(oil),
|
||||
|
@ -725,7 +740,9 @@ const layer = createLayer(id, function (this: BaseLayer) {
|
|||
title: "Blaster Burner",
|
||||
description: "The Oil Burner can now increase your auto smelting multi."
|
||||
},
|
||||
style: { color: colorText }
|
||||
style() {
|
||||
return this.bought.value ? "" : { color: colorText };
|
||||
}
|
||||
})),
|
||||
createUpgrade(() => ({
|
||||
resource: noPersist(oil),
|
||||
|
@ -734,7 +751,9 @@ const layer = createLayer(id, function (this: BaseLayer) {
|
|||
title: "Oil Integration",
|
||||
description: "Reduce Oil Pump's coal consumption multipler from 5 to 4"
|
||||
},
|
||||
style: { color: colorText }
|
||||
style() {
|
||||
return this.bought.value ? "" : { color: colorText };
|
||||
}
|
||||
})),
|
||||
createUpgrade(() => ({
|
||||
resource: noPersist(oil),
|
||||
|
@ -748,7 +767,9 @@ const layer = createLayer(id, function (this: BaseLayer) {
|
|||
</>
|
||||
))
|
||||
},
|
||||
style: { color: colorText }
|
||||
style() {
|
||||
return this.bought.value ? "" : { color: colorText };
|
||||
}
|
||||
}))
|
||||
];
|
||||
const row3Upgrades = [
|
||||
|
@ -761,7 +782,9 @@ const layer = createLayer(id, function (this: BaseLayer) {
|
|||
},
|
||||
visibility: () =>
|
||||
showIf(management.elfTraining.oilElfTraining.milestones[4].earned.value),
|
||||
style: { color: colorText }
|
||||
style() {
|
||||
return this.bought.value ? "" : { color: colorText };
|
||||
}
|
||||
})),
|
||||
createUpgrade(() => ({
|
||||
resource: noPersist(oil),
|
||||
|
@ -772,7 +795,9 @@ const layer = createLayer(id, function (this: BaseLayer) {
|
|||
},
|
||||
visibility: () =>
|
||||
showIf(management.elfTraining.oilElfTraining.milestones[4].earned.value),
|
||||
style: { color: colorText }
|
||||
style() {
|
||||
return this.bought.value ? "" : { color: colorText };
|
||||
}
|
||||
})),
|
||||
createUpgrade(() => ({
|
||||
resource: noPersist(oil),
|
||||
|
@ -788,7 +813,9 @@ const layer = createLayer(id, function (this: BaseLayer) {
|
|||
},
|
||||
visibility: () =>
|
||||
showIf(management.elfTraining.oilElfTraining.milestones[4].earned.value),
|
||||
style: { color: colorText }
|
||||
style() {
|
||||
return this.bought.value ? "" : { color: colorText };
|
||||
}
|
||||
})),
|
||||
createUpgrade(() => ({
|
||||
resource: noPersist(oil),
|
||||
|
@ -799,7 +826,9 @@ const layer = createLayer(id, function (this: BaseLayer) {
|
|||
},
|
||||
visibility: () =>
|
||||
showIf(management.elfTraining.oilElfTraining.milestones[4].earned.value),
|
||||
style: { color: colorText }
|
||||
style() {
|
||||
return this.bought.value ? "" : { color: colorText };
|
||||
}
|
||||
})),
|
||||
createUpgrade(() => ({
|
||||
resource: noPersist(oil),
|
||||
|
@ -810,7 +839,9 @@ const layer = createLayer(id, function (this: BaseLayer) {
|
|||
},
|
||||
visibility: () =>
|
||||
showIf(management.elfTraining.oilElfTraining.milestones[4].earned.value),
|
||||
style: { color: colorText }
|
||||
style() {
|
||||
return this.bought.value ? "" : { color: colorText };
|
||||
}
|
||||
}))
|
||||
];
|
||||
const coalConsumption = createSequentialModifier(() => [
|
||||
|
@ -964,7 +995,8 @@ const layer = createLayer(id, function (this: BaseLayer) {
|
|||
multiplier: 50,
|
||||
description: "350 toys",
|
||||
enabled: toys.milestones.milestone4.earned
|
||||
}))
|
||||
})),
|
||||
reindeer.reindeer.donner.modifier
|
||||
]) as WithRequired<Modifier, "description" | "revert">;
|
||||
const computedOilSpeed = computed(() => oilSpeed.apply(0));
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ import dyes from "./dyes";
|
|||
import elves, { ElfBuyable } from "./elves";
|
||||
import management from "./management";
|
||||
import plastic from "./plastic";
|
||||
import reindeer from "./reindeer";
|
||||
import ribbon from "./ribbon";
|
||||
import trees from "./trees";
|
||||
import workshop from "./workshop";
|
||||
|
@ -423,7 +424,8 @@ const layer = createLayer(id, function (this: BaseLayer) {
|
|||
multiplier: wrappingPaper.boosts.sunshine1,
|
||||
description: "Sunshine Wrapping Paper",
|
||||
enabled: () => Decimal.gte(wrappingPaper.boosts.sunshine1.value, 2)
|
||||
}))
|
||||
})),
|
||||
reindeer.reindeer.prancer.modifier
|
||||
]) as WithRequired<Modifier, "description" | "revert">;
|
||||
const ashCost = createSequentialModifier(() => [
|
||||
createMultiplicativeModifier(() => ({
|
||||
|
|
|
@ -37,6 +37,7 @@ import oil from "./oil";
|
|||
import paper from "./paper";
|
||||
import workshop from "./workshop";
|
||||
import toys from "./toys";
|
||||
import reindeer from "./reindeer";
|
||||
|
||||
const id = "plastic";
|
||||
const day = 10;
|
||||
|
@ -383,7 +384,8 @@ const layer = createLayer(id, function (this: BaseLayer) {
|
|||
createMultiplicativeModifier(() => ({
|
||||
multiplier: () => dyes.boosts.white1.value,
|
||||
description: "White Dye Boost"
|
||||
}))
|
||||
})),
|
||||
reindeer.reindeer.blitzen.modifier
|
||||
]);
|
||||
const computedPlasticGain = computed(() => plasticGain.apply(0));
|
||||
|
||||
|
|
592
src/data/layers/reindeer.tsx
Normal file
592
src/data/layers/reindeer.tsx
Normal file
|
@ -0,0 +1,592 @@
|
|||
/**
|
||||
* @module
|
||||
* @hidden
|
||||
*/
|
||||
import HotkeyVue from "components/Hotkey.vue";
|
||||
import Spacer from "components/layout/Spacer.vue";
|
||||
import Modal from "components/Modal.vue";
|
||||
import { createCollapsibleModifierSections } from "data/common";
|
||||
import { main } from "data/projEntry";
|
||||
import { createBar, GenericBar } from "features/bars/bar";
|
||||
import { createClickable } from "features/clickables/clickable";
|
||||
import { jsx } from "features/feature";
|
||||
import { createHotkey, GenericHotkey } from "features/hotkey";
|
||||
import { createUpgrade } from "features/upgrades/upgrade";
|
||||
import { globalBus } from "game/events";
|
||||
import { BaseLayer, createLayer } from "game/layers";
|
||||
import {
|
||||
createAdditiveModifier,
|
||||
createMultiplicativeModifier,
|
||||
createSequentialModifier
|
||||
} from "game/modifiers";
|
||||
import { persistent } from "game/persistence";
|
||||
import Decimal, { DecimalSource, format, formatTime, formatWhole } from "util/bignum";
|
||||
import { Direction } from "util/common";
|
||||
import { render, renderGrid } from "util/vue";
|
||||
import { computed, ref, unref, watchEffect } from "vue";
|
||||
import boxes from "./boxes";
|
||||
import cloth from "./cloth";
|
||||
import coal from "./coal";
|
||||
import dyes from "./dyes";
|
||||
import metal from "./metal";
|
||||
import oil from "./oil";
|
||||
import paper from "./paper";
|
||||
import plastic from "./plastic";
|
||||
import "./styles/reindeer.css";
|
||||
import trees from "./trees";
|
||||
|
||||
const id = "reindeer";
|
||||
const day = 21;
|
||||
const layer = createLayer(id, function (this: BaseLayer) {
|
||||
const name = "Reindeer";
|
||||
const color = "saddlebrown";
|
||||
|
||||
const feedGoal = 1.5e3;
|
||||
|
||||
const timeSinceFocus = persistent<number>(0);
|
||||
|
||||
const currMultiplier = persistent<DecimalSource>(1);
|
||||
const currTargets = persistent<Record<string, boolean>>({});
|
||||
const currCooldown = persistent<number>(0);
|
||||
const crit = persistent<number>(0);
|
||||
|
||||
const maxMultiplier = createSequentialModifier(() => [
|
||||
createMultiplicativeModifier(() => ({
|
||||
multiplier: 2,
|
||||
description: "Carry food in boxes",
|
||||
enabled: upgrade4.bought
|
||||
}))
|
||||
]);
|
||||
const computedMaxMultiplier = computed(() => maxMultiplier.apply(2));
|
||||
const targetsCount = createSequentialModifier(() => [
|
||||
createAdditiveModifier(() => ({
|
||||
addend: 1,
|
||||
description: "Guide to Reindeer Handling",
|
||||
enabled: upgrade3.bought
|
||||
})),
|
||||
createAdditiveModifier(() => ({
|
||||
addend: crit,
|
||||
description: "Metal clapper",
|
||||
enabled: upgrade5.bought
|
||||
}))
|
||||
]);
|
||||
const computedTargetsCount = computed(() => targetsCount.apply(1));
|
||||
const computedMaxCooldown = computed(() => 10);
|
||||
|
||||
function focus() {
|
||||
let targetsSelected = 0;
|
||||
currTargets.value = {};
|
||||
timeSinceFocus.value = 0;
|
||||
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++;
|
||||
if (upgrade8.bought.value) {
|
||||
selectedReindeer.onClick();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
focus();
|
||||
}
|
||||
}));
|
||||
|
||||
const cooldown = createSequentialModifier(() => [
|
||||
createMultiplicativeModifier(() => ({
|
||||
multiplier: 0.5,
|
||||
description: "Pile of coal",
|
||||
enabled: upgrade2.bought
|
||||
}))
|
||||
]);
|
||||
const computedCooldown = computed(() => cooldown.apply(10));
|
||||
|
||||
function createReindeer(options: {
|
||||
name: string;
|
||||
key: string;
|
||||
boostDescription: string;
|
||||
boostAmount: DecimalSource;
|
||||
}) {
|
||||
const timesFed = persistent<DecimalSource>(0);
|
||||
const progress = persistent<DecimalSource>(0);
|
||||
|
||||
const hotkey = createHotkey(() => ({
|
||||
key: "Numpad " + options.key,
|
||||
description: "Feed " + options.name,
|
||||
enabled: main.days[day - 1].opened,
|
||||
onPress: clickable.onClick
|
||||
})) as GenericHotkey;
|
||||
|
||||
const clickable = createClickable(() => {
|
||||
const progressBar = createBar(() => ({
|
||||
direction: Direction.Right,
|
||||
width: 140,
|
||||
height: 10,
|
||||
style: "margin-top: 8px",
|
||||
borderStyle: "border-color: black",
|
||||
baseStyle: "margin-top: -1px",
|
||||
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)
|
||||
}));
|
||||
|
||||
const modifier = createMultiplicativeModifier(() => ({
|
||||
multiplier: effect,
|
||||
description: options.name,
|
||||
enabled: () => Decimal.gt(timesFed.value, 0)
|
||||
}));
|
||||
|
||||
const effect = computed(() =>
|
||||
Decimal.times(options.boostAmount, timesFed.value)
|
||||
.add(1)
|
||||
.pow(upgrade9.bought.value ? 1.1 : 1)
|
||||
);
|
||||
|
||||
return {
|
||||
...options,
|
||||
hotkey,
|
||||
timesFed,
|
||||
progress,
|
||||
effect,
|
||||
modifier,
|
||||
display: {
|
||||
title: jsx(() => (
|
||||
<h3>
|
||||
Feed {options.name} <HotkeyVue hotkey={hotkey} />
|
||||
</h3>
|
||||
)),
|
||||
description: jsx(() => (
|
||||
<>
|
||||
<br />
|
||||
Each time you feed {options.name} will increase your{" "}
|
||||
{options.boostDescription} by +{format(options.boostAmount)}x
|
||||
<Spacer />
|
||||
Currently {format(effect.value)}x
|
||||
<br />
|
||||
{render(progressBar)}
|
||||
</>
|
||||
))
|
||||
},
|
||||
style: {
|
||||
width: "160px",
|
||||
height: "160px"
|
||||
},
|
||||
canClick() {
|
||||
return Decimal.gte(progress.value, computedCooldown.value);
|
||||
},
|
||||
onClick() {
|
||||
if (!unref(clickable.canClick)) {
|
||||
return;
|
||||
}
|
||||
let amount = Decimal.div(progress.value, computedCooldown.value);
|
||||
if (upgrade1.bought.value) {
|
||||
amount = Decimal.times(amount, 2);
|
||||
}
|
||||
timesFed.value = Decimal.add(timesFed.value, amount);
|
||||
progress.value = 0;
|
||||
},
|
||||
update(diff: number) {
|
||||
if (Decimal.gte(progress.value, computedCooldown.value)) {
|
||||
progress.value = computedCooldown.value;
|
||||
} else {
|
||||
let amount: DecimalSource = diff;
|
||||
const isFocused = currTargets.value[options.name] && currCooldown.value > 0;
|
||||
if (isFocused) {
|
||||
amount = Decimal.times(amount, currMultiplier.value);
|
||||
}
|
||||
progress.value = Decimal.add(progress.value, amount);
|
||||
if (clickable.isHolding.value || (upgrade8.bought.value && isFocused)) {
|
||||
clickable.onClick();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
return clickable;
|
||||
}
|
||||
const dasher = createReindeer({
|
||||
name: "Dasher",
|
||||
key: "7",
|
||||
boostDescription: "log gain",
|
||||
boostAmount: 1
|
||||
});
|
||||
const dancer = createReindeer({
|
||||
name: "Dancer",
|
||||
key: "8",
|
||||
boostDescription: "coal gain",
|
||||
boostAmount: 0.1
|
||||
});
|
||||
const prancer = createReindeer({
|
||||
name: "Prancer",
|
||||
key: "9",
|
||||
boostDescription: "paper gain",
|
||||
boostAmount: 0.1
|
||||
});
|
||||
const vixen = createReindeer({
|
||||
name: "Vixen",
|
||||
key: "4",
|
||||
boostDescription: "boxes gain",
|
||||
boostAmount: 0.1
|
||||
});
|
||||
const comet = createReindeer({
|
||||
name: "Comet",
|
||||
key: "5",
|
||||
boostDescription: "metal gain",
|
||||
boostAmount: 0.1
|
||||
});
|
||||
const cupid = createReindeer({
|
||||
name: "Cupid",
|
||||
key: "6",
|
||||
boostDescription: "cloth actions",
|
||||
boostAmount: 0.1
|
||||
});
|
||||
const donner = createReindeer({
|
||||
name: "Donner",
|
||||
key: "1",
|
||||
boostDescription: "oil gain",
|
||||
boostAmount: 0.01
|
||||
});
|
||||
const blitzen = createReindeer({
|
||||
name: "Blitzen",
|
||||
key: "2",
|
||||
boostDescription: "plastic gain",
|
||||
boostAmount: 0.1
|
||||
});
|
||||
const rudolph = createReindeer({
|
||||
name: "Rudolph",
|
||||
key: "3",
|
||||
boostDescription: "dye gain",
|
||||
boostAmount: 0.01
|
||||
});
|
||||
// order is designed so hotkeys appear 1-9, even though they're displayed in numpad order in the layer itself
|
||||
const reindeer = { donner, blitzen, rudolph, vixen, comet, cupid, dasher, dancer, prancer };
|
||||
|
||||
const sumTimesFed = computed(() =>
|
||||
Object.values(reindeer)
|
||||
.map(r => r.timesFed.value)
|
||||
.reduce(Decimal.add, Decimal.dZero)
|
||||
);
|
||||
|
||||
const upgrade1 = createUpgrade(() => ({
|
||||
resource: trees.logs,
|
||||
cost: 1e97,
|
||||
style: {
|
||||
width: "160px"
|
||||
},
|
||||
display: {
|
||||
title: "Sawdust?",
|
||||
description:
|
||||
"Adding some sawdust to the feed allows you to make more of it. Each feed action counts twice"
|
||||
}
|
||||
}));
|
||||
const upgrade2 = createUpgrade(() => ({
|
||||
resource: coal.coal,
|
||||
cost: 1e167,
|
||||
style: {
|
||||
width: "160px"
|
||||
},
|
||||
display: {
|
||||
title: "Pile of coal",
|
||||
description:
|
||||
"Building a threatening pile of coal encourages the reindeer to behave. Each reindeer eats twice as fast"
|
||||
}
|
||||
}));
|
||||
const upgrade3 = createUpgrade(() => ({
|
||||
resource: paper.paper,
|
||||
cost: 1e117,
|
||||
style: {
|
||||
width: "160px"
|
||||
},
|
||||
display: {
|
||||
title: "Guide to Reindeer Handling",
|
||||
description:
|
||||
"Written reindeer handling instructions allow you to help more focus at once. Increase focus targets by one"
|
||||
}
|
||||
}));
|
||||
const upgrade4 = createUpgrade(() => ({
|
||||
resource: boxes.boxes,
|
||||
cost: 1e102,
|
||||
style: {
|
||||
width: "160px"
|
||||
},
|
||||
display: {
|
||||
title: "Carry food in boxes",
|
||||
description:
|
||||
"Carrying reindeer food in boxes allows you to distribute it faster. Double the maximum focus multiplier"
|
||||
}
|
||||
}));
|
||||
const upgrade5 = createUpgrade(() => ({
|
||||
resource: metal.metal,
|
||||
cost: 1e67,
|
||||
style: {
|
||||
width: "160px"
|
||||
},
|
||||
display: {
|
||||
title: "Metal clapper",
|
||||
description:
|
||||
'Striking two rods of metal can help get more reindeer\'s attention when done right. "Critical" focuses now affect up to two additional reindeer'
|
||||
}
|
||||
}));
|
||||
const upgrade6 = createUpgrade(() => ({
|
||||
resource: cloth.cloth,
|
||||
cost: 1e20,
|
||||
style: {
|
||||
width: "160px"
|
||||
},
|
||||
display: {
|
||||
title: "Focus bar padding",
|
||||
description:
|
||||
"Adding padding to the focus bar lets you slow it down when it's closer to the max value"
|
||||
}
|
||||
}));
|
||||
const upgrade7 = createUpgrade(() => ({
|
||||
resource: oil.oil,
|
||||
cost: 4e25,
|
||||
style: {
|
||||
width: "160px"
|
||||
},
|
||||
display: {
|
||||
title: "Oil can do that?",
|
||||
description:
|
||||
"Using a lot of oil somehow let's reindeers focus themselves with a random value when left un-focused for 10s"
|
||||
}
|
||||
}));
|
||||
const upgrade8 = createUpgrade(() => ({
|
||||
resource: plastic.plastic,
|
||||
cost: 1e22,
|
||||
style: {
|
||||
width: "160px"
|
||||
},
|
||||
display: {
|
||||
title: "Autoamted feeder",
|
||||
description: "An automated feeder let's focused reindeer eat automatically"
|
||||
}
|
||||
}));
|
||||
const upgrade9 = createUpgrade(() => ({
|
||||
resource: dyes.dyes.white.amount,
|
||||
cost: 7.5e7,
|
||||
style: {
|
||||
width: "160px"
|
||||
},
|
||||
display: {
|
||||
title: "Colorful food",
|
||||
description:
|
||||
"Adding some non-toxic dyes to the food makes them more powerful. Raise each reindeer's effect to the ^1.1"
|
||||
}
|
||||
}));
|
||||
const upgrades = {
|
||||
upgrade1,
|
||||
upgrade2,
|
||||
upgrade3,
|
||||
upgrade4,
|
||||
upgrade5,
|
||||
upgrade6,
|
||||
upgrade7,
|
||||
upgrade8,
|
||||
upgrade9
|
||||
};
|
||||
|
||||
const [generalTab, generalTabCollapsed] = createCollapsibleModifierSections(() => [
|
||||
{
|
||||
title: "Max Focus Multiplier",
|
||||
modifier: maxMultiplier,
|
||||
base: 2
|
||||
},
|
||||
{
|
||||
title: "Focus Targets",
|
||||
modifier: targetsCount,
|
||||
base: 1
|
||||
},
|
||||
{
|
||||
title: "Eating duration",
|
||||
modifier: cooldown,
|
||||
base: 10
|
||||
}
|
||||
]);
|
||||
const showModifiersModal = ref(false);
|
||||
const modifiersModal = jsx(() => (
|
||||
<Modal
|
||||
modelValue={showModifiersModal.value}
|
||||
onUpdate:modelValue={(value: boolean) => (showModifiersModal.value = value)}
|
||||
v-slots={{
|
||||
header: () => <h2>{name} Modifiers</h2>,
|
||||
body: generalTab
|
||||
}}
|
||||
/>
|
||||
));
|
||||
|
||||
globalBus.on("update", diff => {
|
||||
if (Decimal.lt(main.day.value, day)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Object.values(reindeer).forEach(reindeer => reindeer.update(diff));
|
||||
|
||||
currCooldown.value = Math.max(currCooldown.value - diff, 0);
|
||||
|
||||
let auto = false;
|
||||
if (upgrade7.bought.value) {
|
||||
timeSinceFocus.value += diff;
|
||||
if (timeSinceFocus.value > 10) {
|
||||
auto = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (Decimal.eq(currCooldown.value, 0)) {
|
||||
let speed = 1000;
|
||||
if (auto) {
|
||||
speed = Math.random() * 1000;
|
||||
}
|
||||
let stoppedAt = 1 - Math.abs(Math.sin((Date.now() / speed) * 2));
|
||||
if (upgrade6.bought.value) {
|
||||
stoppedAt = 1 - (1 - stoppedAt) ** 2;
|
||||
}
|
||||
crit.value = stoppedAt > 0.975 ? 2 : stoppedAt > 0.9 ? 1 : 0;
|
||||
currMultiplier.value = Decimal.pow(computedMaxMultiplier.value, stoppedAt);
|
||||
if (auto) {
|
||||
focus();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const dayProgress = createBar(() => ({
|
||||
direction: Direction.Right,
|
||||
width: 600,
|
||||
height: 25,
|
||||
fillStyle: `backgroundColor: ${color}`,
|
||||
progress: () => (main.day.value === day ? Decimal.div(sumTimesFed.value, feedGoal) : 1),
|
||||
display: jsx(() =>
|
||||
main.day.value === day ? (
|
||||
<>
|
||||
{formatWhole(sumTimesFed.value)}/{formatWhole(feedGoal)}
|
||||
</>
|
||||
) : (
|
||||
""
|
||||
)
|
||||
)
|
||||
})) as GenericBar;
|
||||
|
||||
watchEffect(() => {
|
||||
if (main.day.value === day && Decimal.gte(sumTimesFed.value, feedGoal)) {
|
||||
main.completeDay();
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
name,
|
||||
day,
|
||||
color,
|
||||
reindeer,
|
||||
generalTabCollapsed,
|
||||
timeSinceFocus,
|
||||
currMultiplier,
|
||||
currTargets,
|
||||
currCooldown,
|
||||
upgrades,
|
||||
crit,
|
||||
minWidth: 700,
|
||||
display: jsx(() => (
|
||||
<>
|
||||
<div>
|
||||
{main.day.value === day
|
||||
? `Feed reindeer ${formatWhole(feedGoal)} times to complete the day`
|
||||
: `${name} Complete!`}{" "}
|
||||
-{" "}
|
||||
<button
|
||||
class="button"
|
||||
style="display: inline-block;"
|
||||
onClick={() => (showModifiersModal.value = true)}
|
||||
>
|
||||
Check Modifiers
|
||||
</button>
|
||||
</div>
|
||||
{render(dayProgress)}
|
||||
{render(modifiersModal)}
|
||||
<Spacer />
|
||||
<div>You have fed reindeer {formatWhole(sumTimesFed.value)} times</div>
|
||||
<Spacer />
|
||||
{renderGrid(
|
||||
[focusButton],
|
||||
[focusMeter],
|
||||
[dasher, dancer, prancer],
|
||||
[vixen, comet, cupid],
|
||||
[donner, blitzen, rudolph]
|
||||
)}
|
||||
<Spacer />
|
||||
{renderGrid(
|
||||
[upgrade1, upgrade2, upgrade3],
|
||||
[upgrade4, upgrade5, upgrade6],
|
||||
[upgrade7, upgrade8, upgrade9]
|
||||
)}
|
||||
</>
|
||||
)),
|
||||
minimizedDisplay: jsx(() => (
|
||||
<div>
|
||||
{name} <span class="desc">{format(sumTimesFed.value)} times fed</span>
|
||||
</div>
|
||||
))
|
||||
};
|
||||
});
|
||||
|
||||
export default layer;
|
|
@ -93,7 +93,6 @@ const layer = createLayer(id, () => {
|
|||
if (!unref(makeRibbon.canClick)) {
|
||||
return;
|
||||
}
|
||||
currentDyeType.value.amount.value = 0;
|
||||
currentDyeType.value.buyable.amount.value = 0;
|
||||
cloth.cloth.value = Decimal.sub(cloth.cloth.value, 1e9);
|
||||
ribbon.value = Decimal.add(ribbon.value, 1);
|
||||
|
|
225
src/data/layers/sleigh.tsx
Normal file
225
src/data/layers/sleigh.tsx
Normal file
|
@ -0,0 +1,225 @@
|
|||
/**
|
||||
* @module
|
||||
* @hidden
|
||||
*/
|
||||
import Spacer from "components/layout/Spacer.vue";
|
||||
import { createCollapsibleMilestones} from "data/common";
|
||||
import { main } from "data/projEntry";
|
||||
import { createBar } from "features/bars/bar";
|
||||
import { jsx, showIf } from "features/feature";
|
||||
import { createMilestone } from "features/milestones/milestone";
|
||||
import { BaseLayer, createLayer } from "game/layers";
|
||||
import Decimal, { DecimalSource, format, formatWhole } from "util/bignum";
|
||||
import { Direction} from "util/common";
|
||||
import { render } from "util/vue";
|
||||
import { computed, watchEffect } from "vue";
|
||||
import management from "./management";
|
||||
import trees from "./trees";
|
||||
import metal from "./metal";
|
||||
import plastic from "./plastic"
|
||||
import { createBuyable, GenericBuyable } from "features/buyable";
|
||||
import { Resource } from "features/resources/resource";
|
||||
import { isArray } from "@vue/shared";
|
||||
|
||||
const id = "sleigh";
|
||||
const day = 22;
|
||||
const layer = createLayer(id, function (this: BaseLayer) {
|
||||
const name = "Sleigh";
|
||||
const color = "#D71830";
|
||||
const colorDark = "#A01020";
|
||||
function displayCost(
|
||||
res: Resource<DecimalSource> | Resource<DecimalSource>[],
|
||||
cost: DecimalSource,
|
||||
label: string
|
||||
) {
|
||||
const affordable = (isArray(res) ? res : [res]).every(res => Decimal.gte(res.value, cost));
|
||||
return (
|
||||
<span class={affordable ? "" : "unaffordable"}>
|
||||
{format(cost)} {label}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
const sleighProgress = computed(() => sleigh.amount)
|
||||
const sleighCost = computed(() => {
|
||||
let v = sleighProgress.value.value;
|
||||
return {
|
||||
wood: Decimal.mul(1e60, Decimal.pow(1.2, v)),
|
||||
metal: Decimal.mul(1e40, Decimal.pow(1.1, v)),
|
||||
plastic: Decimal.mul(1e10, Decimal.pow(1.05, v))
|
||||
};
|
||||
});
|
||||
const sleigh = createBuyable(() => ({
|
||||
display: jsx(() => (
|
||||
<>
|
||||
<b style="font-size: x-large">Fix 1% of the sleigh</b>
|
||||
<br />
|
||||
<br />
|
||||
<span style="font-size: large">
|
||||
Cost: {displayCost(trees.logs, sleighCost.value.wood, "logs")},
|
||||
{displayCost(metal.metal, sleighCost.value.metal, "metal")},
|
||||
{displayCost(plastic.plastic, sleighCost.value.plastic, "plastic")}
|
||||
</span>
|
||||
</>
|
||||
)),
|
||||
canPurchase(): boolean {
|
||||
return (
|
||||
sleighCost.value.wood.lte(trees.logs.value) &&
|
||||
sleighCost.value.metal.lte(metal.metal.value) &&
|
||||
sleighCost.value.plastic.lte(plastic.plastic.value)
|
||||
);
|
||||
},
|
||||
onPurchase() {
|
||||
this.amount.value = Decimal.add(this.amount.value, 1);
|
||||
},
|
||||
visibility: () => showIf(Decimal.lt(sleighProgress.value.value, 100)),
|
||||
style: "width: 600px"
|
||||
})) as GenericBuyable;
|
||||
|
||||
const shouldShowPopups = computed(() => true);
|
||||
const milestone1 = createMilestone(() => ({
|
||||
display: {
|
||||
requirement: "1% Sleigh Fixed",
|
||||
effectDisplay: "Ore gives 5% more metal for each % of sleigh fixed"
|
||||
},
|
||||
shouldEarn: () => Decimal.gte(sleighProgress.value.value, 1),
|
||||
showPopups: shouldShowPopups
|
||||
}));
|
||||
const milestone2 = createMilestone(() => ({
|
||||
display: {
|
||||
requirement: "10% Sleigh Fixed",
|
||||
effectDisplay: "Gain an additional 5% more wood for each 5% of sleigh fixed"
|
||||
},
|
||||
shouldEarn: () => Decimal.gte(sleighProgress.value.value, 10),
|
||||
showPopups: shouldShowPopups
|
||||
}));
|
||||
const milestone3 = createMilestone(() => ({
|
||||
display: {
|
||||
requirement: "20% Sleigh Fixed",
|
||||
effectDisplay: "Gain an additional 5% more plastic for each 5% of sleigh fixed"
|
||||
},
|
||||
shouldEarn: () => Decimal.gte(sleighProgress.value.value, 20),
|
||||
showPopups: shouldShowPopups
|
||||
}));
|
||||
const milestone4 = createMilestone(() => ({
|
||||
display: {
|
||||
requirement: "30% Sleigh Fixed",
|
||||
effectDisplay: "All automatic metal actions are doubled"
|
||||
},
|
||||
shouldEarn: () => Decimal.gte(sleighProgress.value.value, 30),
|
||||
showPopups: shouldShowPopups
|
||||
}));
|
||||
const milestone5 = createMilestone(() => ({
|
||||
display: {
|
||||
requirement: "40% Sleigh Fixed",
|
||||
effectDisplay: "Plastic gain is doubled"
|
||||
},
|
||||
shouldEarn: () => Decimal.gte(sleighProgress.value.value, 40),
|
||||
showPopups: shouldShowPopups
|
||||
}));
|
||||
const milestone6 = createMilestone(() => ({
|
||||
display: {
|
||||
requirement: "50% Sleigh Fixed",
|
||||
effectDisplay: "Trees give 10x as many logs"
|
||||
},
|
||||
shouldEarn: () => Decimal.gte(sleighProgress.value.value, 50),
|
||||
showPopups: shouldShowPopups
|
||||
}));
|
||||
const milestone7 = createMilestone(() => ({
|
||||
display: {
|
||||
requirement: "75% Sleigh Fixed",
|
||||
effectDisplay: "Gain 10 extra refineries for every 2% of sleigh fixed"
|
||||
},
|
||||
shouldEarn: () => Decimal.gte(sleighProgress.value.value, 75),
|
||||
showPopups: shouldShowPopups
|
||||
}));
|
||||
const milestone8 = createMilestone(() => ({
|
||||
display: {
|
||||
requirement: "100% Sleigh Fixed",
|
||||
effectDisplay: "Metal per ore is raised to the 1.2th power"
|
||||
},
|
||||
shouldEarn: () => Decimal.gte(sleighProgress.value.value, 100),
|
||||
showPopups: shouldShowPopups
|
||||
}));
|
||||
const milestones = {
|
||||
milestone1,
|
||||
milestone2,
|
||||
milestone3,
|
||||
milestone4,
|
||||
milestone5,
|
||||
milestone6,
|
||||
milestone7,
|
||||
milestone8
|
||||
};
|
||||
const { collapseMilestones, display: milestonesDisplay } =
|
||||
createCollapsibleMilestones(milestones);
|
||||
|
||||
const dayProgress = createBar(() => ({
|
||||
direction: Direction.Right,
|
||||
width: 600,
|
||||
height: 25,
|
||||
fillStyle: `backgroundColor: ${colorDark}`,
|
||||
progress: () =>
|
||||
main.day.value === day || main.currentlyMastering.value?.name === name
|
||||
? Decimal.div(sleighProgress.value.value, 100)
|
||||
: 1,
|
||||
display: jsx(() =>
|
||||
main.day.value === day || main.currentlyMastering.value?.name === name ? (
|
||||
<>{formatWhole(sleighProgress.value.value)}%</>
|
||||
) : (
|
||||
""
|
||||
)
|
||||
)
|
||||
}));
|
||||
|
||||
watchEffect(() => {
|
||||
if (main.day.value === day && Decimal.gte(sleighProgress.value.value, 100)) {
|
||||
main.completeDay();
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
name,
|
||||
day,
|
||||
color,
|
||||
sleighProgress,
|
||||
milestones,
|
||||
collapseMilestones,
|
||||
minWidth: 700,
|
||||
sleigh,
|
||||
display: jsx(() => (
|
||||
<>
|
||||
<div>
|
||||
{main.day.value === day
|
||||
? `Fix the sleigh to complete the day`
|
||||
: `${name} Complete!`}
|
||||
</div>
|
||||
{render(dayProgress)}
|
||||
<Spacer />
|
||||
<div>
|
||||
<span>The sleigh is </span>
|
||||
<h2 style={`color: ${color}; text-shadow: 0 0 10px ${color}`}>
|
||||
{formatWhole(sleighProgress.value.value)}
|
||||
</h2>
|
||||
% fixed
|
||||
</div>
|
||||
{Decimal.lt(sleighProgress.value.value, 100) ||
|
||||
management.elfTraining.expandersElfTraining.milestones[2].earned.value ? (
|
||||
<Spacer />
|
||||
) : null}
|
||||
{render(sleigh)}
|
||||
<Spacer />
|
||||
{milestonesDisplay()}
|
||||
</>
|
||||
)),
|
||||
minimizedDisplay: jsx(() => (
|
||||
<div>
|
||||
{name}{" "}
|
||||
<span class="desc">
|
||||
{formatWhole(sleighProgress.value.value)}% sleigh
|
||||
</span>
|
||||
</div>
|
||||
)),
|
||||
};
|
||||
});
|
||||
|
||||
export default layer;
|
|
@ -64,7 +64,7 @@
|
|||
left: 0px;
|
||||
right: 0px;
|
||||
position: absolute;
|
||||
background-color: var(--raised-background);
|
||||
background-color: snow;
|
||||
overflow: hidden;
|
||||
z-index: 1;
|
||||
}
|
||||
|
@ -109,7 +109,7 @@
|
|||
.comp-info {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: -10px;
|
||||
right: 0px;
|
||||
padding: 5px 10px;
|
||||
|
||||
width: max-content;
|
||||
|
@ -125,13 +125,14 @@
|
|||
pointer-events: none;
|
||||
transition: transform 0.3s;
|
||||
|
||||
z-index: -1;
|
||||
z-index: -2;
|
||||
}
|
||||
.comp-list .comp:nth-child(2n - 1) .comp-info {
|
||||
right: -85px;
|
||||
right: -75px;
|
||||
}
|
||||
.comp-list .comp:hover .comp-info {
|
||||
transform: translateX(calc(20px + 100%));
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.comp-list {
|
||||
|
@ -150,8 +151,10 @@
|
|||
justify-content: space-evenly;
|
||||
align-items: flex-start;
|
||||
align-content: flex-start;
|
||||
justify-content: flex-start;
|
||||
width: 148px;
|
||||
direction: ltr;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.comp-list::after {
|
||||
|
@ -159,6 +162,7 @@
|
|||
position: absolute;
|
||||
border-right: solid 2px var(--locked);
|
||||
background: var(--raised-background);
|
||||
box-shadow: 0 2px 10px #0007;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
|
@ -174,6 +178,11 @@
|
|||
pointer-events: all;
|
||||
}
|
||||
|
||||
.comp-list .comp > img:first-child {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
.comp-list .comp:nth-child(3)::after,
|
||||
.comp-list .comp:nth-child(4)::after {
|
||||
content: "";
|
||||
|
@ -190,7 +199,7 @@
|
|||
.comp-list .comp:nth-child(4)::after {
|
||||
left: -50px;
|
||||
}
|
||||
.comp-list .comp img.selected:not(.producedItem) {
|
||||
.comp-list .comp img.selected, .comp-list .comp img.selected + img {
|
||||
transform: translate(-5px, -5px);
|
||||
filter: drop-shadow(2px 2px 0 var(--foreground)) drop-shadow(5px 5px 5px #0007);
|
||||
}
|
||||
|
|
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);
|
||||
}
|
||||
}
|
|
@ -40,6 +40,7 @@ import workshop from "./workshop";
|
|||
import wrappingPaper from "./wrapping-paper";
|
||||
import toys from "./toys";
|
||||
import factory from "./factory";
|
||||
import reindeer from "./reindeer";
|
||||
const id = "trees";
|
||||
const day = 1;
|
||||
|
||||
|
@ -557,6 +558,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
|
|||
description: "Haul wood in trucks",
|
||||
enabled: factory.upgrades[0][2].bought
|
||||
})),
|
||||
reindeer.reindeer.dasher.modifier,
|
||||
createExponentialModifier(() => ({
|
||||
exponent: 1.2,
|
||||
description: "100% Foundation Completed",
|
||||
|
|
|
@ -30,6 +30,7 @@ import {
|
|||
import { noPersist, persistent } from "game/persistence";
|
||||
import Decimal, { DecimalSource, formatWhole } from "util/bignum";
|
||||
import { Direction, WithRequired } from "util/common";
|
||||
import { loadingSave } from "util/save";
|
||||
import { render } from "util/vue";
|
||||
import { computed, ref, unref, watchEffect } from "vue";
|
||||
import elves from "./elves";
|
||||
|
@ -143,6 +144,15 @@ const layer = createLayer(id, function (this: BaseLayer) {
|
|||
style: "width: 600px; min-height: unset"
|
||||
}));
|
||||
|
||||
watchEffect(() => {
|
||||
if (
|
||||
!loadingSave.value &&
|
||||
Decimal.lt(computedMaxFoundation.value, foundationProgress.value)
|
||||
) {
|
||||
foundationProgress.value = Decimal.min(0, computedMaxFoundation.value);
|
||||
}
|
||||
});
|
||||
|
||||
const buildFoundationHK = createHotkey(() => ({
|
||||
key: "w",
|
||||
description: "Build foundation",
|
||||
|
|
|
@ -31,10 +31,12 @@ import metal from "./layers/metal";
|
|||
import oil from "./layers/oil";
|
||||
import paper from "./layers/paper";
|
||||
import plastic from "./layers/plastic";
|
||||
import reindeer from "./layers/reindeer";
|
||||
import ribbon from "./layers/ribbon";
|
||||
import toys from "./layers/toys";
|
||||
import trees from "./layers/trees";
|
||||
import workshop from "./layers/workshop";
|
||||
import sleigh from "./layers/sleigh";
|
||||
import wrappingPaper from "./layers/wrapping-paper";
|
||||
import boxesSymbol from "./symbols/cardboardBox.png";
|
||||
import clothSymbol from "./symbols/cloth.png";
|
||||
|
@ -48,11 +50,13 @@ import metalSymbol from "./symbols/metal.png";
|
|||
import oilSymbol from "./symbols/oil.png";
|
||||
import paperSymbol from "./symbols/paperStacks.png";
|
||||
import plasticSymbol from "./symbols/plastic.png";
|
||||
import presentsSymbol from "./symbols/presents.png";
|
||||
import reindeerSymbol from "./symbols/reindeer.png";
|
||||
import ribbonsSymbol from "./symbols/ribbons.png";
|
||||
import workshopSymbol from "./symbols/sws.png";
|
||||
import advFactorySymbol from "./symbols/teddyBear.png";
|
||||
import treeSymbol from "./symbols/tree.png";
|
||||
import toysSymbol from "./symbols/truck.png";
|
||||
import advFactorySymbol from "./symbols/teddyBear.png";
|
||||
import advManagementSymbol from "./symbols/workshopMansion.png";
|
||||
import wrappingPaperSymbol from "./symbols/wrappingPaper.png";
|
||||
import snowflakeSymbol from "./symbols/snowflake.svg";
|
||||
|
@ -585,27 +589,29 @@ export const main = createLayer("main", function (this: BaseLayer) {
|
|||
createDay(() => ({
|
||||
day: 20,
|
||||
shouldNotify: false,
|
||||
layer: null, // "presents"
|
||||
symbol: wrappingPaperSymbol,
|
||||
story: "",
|
||||
completedStory: "",
|
||||
layer: "factory",
|
||||
symbol: presentsSymbol,
|
||||
story: "Santa comes by again, and tells you that just toys may not be appealing enough. He tells you that you should probably wrap them in some wrapping paper so that it's more of a surprise. You try to argue that you've already done too much for him and deserve a day off, but Santa argues that it's for the benefit of everyone and that you'll get your vacation soon. Oh well, time to get back to the factory and expand it even more. Here we go again!",
|
||||
completedStory:
|
||||
"That was a lot of work, but it certainly felt worth actually using all those decorative supplies you'd previously made. One more sleepless night down, just a handful more to go. Good Job!",
|
||||
masteredStory: ""
|
||||
})),
|
||||
createDay(() => ({
|
||||
day: 21,
|
||||
shouldNotify: false,
|
||||
layer: null, // "reindeer"
|
||||
symbol: "",
|
||||
story: "",
|
||||
completedStory: "",
|
||||
layer: "reindeer",
|
||||
symbol: reindeerSymbol,
|
||||
story: "Now that the toys are being taken care of, it's time to make sure everything is prepped for the big night. One immediate concern is the reindeer, who are going to have to be in tip-top shape. Fortunately, Santa has a recipe to a very strong vitamin-filled kibble that'll get them pumped in no time!",
|
||||
completedStory:
|
||||
"Alright, now that the reindeer have been given all their ste- vitamins, I mean, they should be prepared for Christmas. Good Job!",
|
||||
masteredStory: ""
|
||||
})),
|
||||
createDay(() => ({
|
||||
day: 22,
|
||||
shouldNotify: false,
|
||||
layer: null, // "sleigh"
|
||||
layer: "sleigh", // "sleigh"
|
||||
symbol: "",
|
||||
story: "",
|
||||
story: "default body",
|
||||
completedStory: "",
|
||||
masteredStory: ""
|
||||
})),
|
||||
|
@ -749,7 +755,9 @@ export const getInitialLayers = (
|
|||
wrappingPaper,
|
||||
ribbon,
|
||||
toys,
|
||||
factory
|
||||
factory,
|
||||
reindeer,
|
||||
sleigh
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
BIN
src/data/symbols/presents.png
Normal file
BIN
src/data/symbols/presents.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.3 KiB |
BIN
src/data/symbols/reindeer.png
Normal file
BIN
src/data/symbols/reindeer.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 57 KiB |
|
@ -89,6 +89,9 @@ document.onkeydown = function (e) {
|
|||
if (e.ctrlKey) {
|
||||
key = "ctrl+" + key;
|
||||
}
|
||||
if (e.code.startsWith("Numpad") && `Numpad ${key}` in hotkeys) {
|
||||
key = "Numpad " + key;
|
||||
}
|
||||
const hotkey = hotkeys[key];
|
||||
if (hotkey && unref(hotkey.enabled)) {
|
||||
e.preventDefault();
|
||||
|
|
|
@ -21,7 +21,7 @@ import type {
|
|||
} from "util/computed";
|
||||
import { processComputable } from "util/computed";
|
||||
import { createLazyProxy } from "util/proxies";
|
||||
import type { InjectionKey, Ref } from "vue";
|
||||
import { computed, InjectionKey, Ref } from "vue";
|
||||
import { ref, shallowReactive, unref } from "vue";
|
||||
|
||||
/** A feature's node in the DOM that has its size tracked. */
|
||||
|
@ -231,6 +231,8 @@ export function createLayer<T extends LayerOptions>(
|
|||
|
||||
processComputable(layer as T, "color");
|
||||
processComputable(layer as T, "display");
|
||||
processComputable(layer as T, "classes");
|
||||
processComputable(layer as T, "style");
|
||||
processComputable(layer as T, "name");
|
||||
setDefault(layer, "name", layer.id);
|
||||
processComputable(layer as T, "minWidth");
|
||||
|
@ -239,6 +241,34 @@ export function createLayer<T extends LayerOptions>(
|
|||
setDefault(layer, "minimizable", true);
|
||||
processComputable(layer as T, "minimizedDisplay");
|
||||
|
||||
const style = layer.style as ProcessedComputable<StyleValue> | undefined;
|
||||
layer.style = computed(() => {
|
||||
let width = unref(layer.minWidth as ProcessedComputable<number | string>);
|
||||
if (typeof width === "number" || !Number.isNaN(parseInt(width))) {
|
||||
width = width + "px";
|
||||
}
|
||||
return [
|
||||
unref(style) ?? "",
|
||||
layer.minimized?.value
|
||||
? {
|
||||
flexGrow: "0",
|
||||
flexShrink: "0",
|
||||
width: "60px",
|
||||
minWidth: "",
|
||||
flexBasis: "",
|
||||
margin: "0"
|
||||
}
|
||||
: {
|
||||
flexGrow: "",
|
||||
flexShrink: "",
|
||||
width: "",
|
||||
minWidth: width,
|
||||
flexBasis: width,
|
||||
margin: ""
|
||||
}
|
||||
];
|
||||
}) as Ref<StyleValue>;
|
||||
|
||||
return layer as unknown as Layer<T>;
|
||||
});
|
||||
}
|
||||
|
|
|
@ -14,7 +14,8 @@ export const {
|
|||
formatSmall,
|
||||
formatLimit,
|
||||
invertOOM,
|
||||
formatGain
|
||||
formatGain,
|
||||
formatList
|
||||
} = numberUtils;
|
||||
|
||||
export type DecimalSource = RawDecimalSource;
|
||||
|
@ -34,6 +35,7 @@ declare global {
|
|||
formatLimit: (list: [DecimalSource, string][], unit: string) => string;
|
||||
invertOOM: (x: DecimalSource) => Decimal;
|
||||
formatGain: (x: DecimalSource) => string;
|
||||
formatList: (x: string[]) => string;
|
||||
}
|
||||
}
|
||||
window.Decimal = Decimal;
|
||||
|
@ -48,5 +50,6 @@ window.formatSmall = formatSmall;
|
|||
window.formatLimit = formatLimit;
|
||||
window.invertOOM = invertOOM;
|
||||
window.formatGain = formatGain;
|
||||
window.formatList = formatList;
|
||||
|
||||
export default Decimal;
|
||||
|
|
|
@ -219,3 +219,9 @@ export function formatGain(gain: DecimalSource) {
|
|||
1: `+${format(gain)}/s`
|
||||
}[Decimal.compare(gain, 0)];
|
||||
}
|
||||
|
||||
export function formatList(list: string[]) {
|
||||
if (list.length <= 0) return "";
|
||||
if (list.length == 1) return list[0];
|
||||
return list.slice(0, -1).join(", ") + " and " + list[list.length - 1];
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue