Add metal layer

This commit is contained in:
Seth Posner 2022-12-06 11:02:34 -08:00
parent 7856d6f5e8
commit 36eb1474af
5 changed files with 540 additions and 23 deletions

View file

@ -30,6 +30,7 @@ import { createUpgrade, Upgrade } from "features/upgrades/upgrade";
import elves from "./elves";
import paper from "./paper";
import boxes from "./boxes";
import metal from "./metal";
interface BetterFertilizerUpgOptions {
canAfford: () => boolean;
@ -294,6 +295,80 @@ const layer = createLayer(id, function (this: BaseLayer) {
}
}));
const activeDrills = persistent<DecimalSource>(0);
const drillCoal = computed(() => Decimal.times(activeDrills.value, 5e7));
const buildDrill = createBuyable(() => ({
resource: metal.metal,
cost() {
let v = this.amount.value;
if (Decimal.gte(v, 100)) v = Decimal.pow(v, 2).div(100);
if (Decimal.gte(v, 10000)) v = Decimal.pow(v, 2).div(10000);
// v = Decimal.pow(0.95, paper.books.drillBook.amount.value).times(v);
return Decimal.pow(v, 1.15).plus(10);
},
display: jsx(() => (
<>
<h3>Mining Drill</h3>
<br />
Dig through the ground to find 50,000,000 coal
<br />
<br />
Currently:
<br />+{format(drillCoal.value)} coal/sec
<br />
<br />
Cost: {formatWhole(unref(buildDrill.cost!))} {buildDrill.resource.displayName}
</>
)),
onPurchase() {
activeDrills.value = Decimal.add(activeDrills.value, 1);
},
style: {
color: colorText,
width: "160px"
}
})) as GenericBuyable & { resource: Resource };
const minDrill = createClickable(() => ({
display: "0",
style: { minHeight: "20px", width: "40px", color: colorText },
canClick() {
return Decimal.gt(activeDrills.value, 0);
},
onClick() {
activeDrills.value = 0;
}
}));
const removeDrill = createClickable(() => ({
display: "-",
style: { minHeight: "20px", width: "40px", color: colorText },
canClick() {
return Decimal.gt(activeDrills.value, 0);
},
onClick() {
activeDrills.value = Decimal.sub(activeDrills.value, 1);
}
}));
const addDrill = createClickable(() => ({
display: "+",
style: { minHeight: "20px", width: "40px", color: colorText },
canClick() {
return Decimal.lt(activeDrills.value, buildDrill.amount.value);
},
onClick() {
activeDrills.value = Decimal.add(activeDrills.value, 1);
}
}));
const maxDrill = createClickable(() => ({
display: "Max",
style: { minHeight: "20px", width: "40px", color: colorText },
canClick() {
return Decimal.lt(activeDrills.value, buildDrill.amount.value);
},
onClick() {
activeDrills.value = buildDrill.amount.value;
}
}));
const warmerCutters = createUpgrade(() => ({
resource: noPersist(coal),
cost: 5,
@ -535,6 +610,15 @@ const layer = createLayer(id, function (this: BaseLayer) {
return Decimal.gt(activeKilns.value, 0);
}
})),
createAdditiveModifier(() => ({
addend() {
return drillCoal.value;
},
description: "Mining Drills",
enabled() {
return Decimal.gt(activeDrills.value, 0);
}
})),
createMultiplicativeModifier(() => ({
multiplier: 2,
description: "Carry coal in boxes",
@ -736,6 +820,7 @@ const layer = createLayer(id, function (this: BaseLayer) {
color: colorCoal,
coal,
totalCoal,
computedCoalGain,
ash,
activeFires,
buildFire,
@ -743,6 +828,8 @@ const layer = createLayer(id, function (this: BaseLayer) {
buildBonfire,
activeKilns,
buildKiln,
activeDrills,
buildDrill,
warmerCutters,
warmerPlanters,
basicFertilizer,
@ -820,6 +907,19 @@ const layer = createLayer(id, function (this: BaseLayer) {
</Column>
</>
) : undefined}
{metal.coalDrill.bought.value ? (
<>
<Spacer />
<Column>
{render(buildDrill)}
<div>
{formatWhole(activeDrills.value)}/
{formatWhole(buildDrill.amount.value)}
</div>
{renderRow(minDrill, removeDrill, addDrill, maxDrill)}
</Column>
</>
) : undefined}
</Row>
<Spacer />
{renderRow(...row1upgrades)}

395
src/data/layers/metal.tsx Normal file
View file

@ -0,0 +1,395 @@
import Spacer from "components/layout/Spacer.vue";
import MainDisplay from "features/resources/MainDisplay.vue";
import Toggle from "components/fields/Toggle.vue"
import Modal from "components/Modal.vue";
import { createCollapsibleModifierSections, setUpDailyProgressTracker } from "data/common";
import { jsx, showIf } from "features/feature";
import { createResource, trackBest } from "features/resources/resource";
import { BaseLayer, createLayer } from "game/layers";
import Decimal, { DecimalSource } from "lib/break_eternity";
import { render, renderRow } from "util/vue";
import { persistent } from "game/persistence";
import { globalBus } from "game/events";
import { createAdditiveModifier, createMultiplicativeModifier, createSequentialModifier } from "game/modifiers";
import { computed, ref, unref } from "vue";
import { createBar } from "features/bars/bar";
import { Direction } from "util/common";
import { format, formatWhole } from "util/break_eternity";
import { createClickable } from "features/clickables/clickable";
import coal from "./coal"
import { createUpgrade, GenericUpgrade } from "features/upgrades/upgrade";
import { noPersist } from "game/persistence"
import { createBuyable, GenericBuyable } from "features/buyable";
const id = "metal";
const day = 7;
const layer = createLayer(id, function (this: BaseLayer) {
const name = "Metal";
const color = "#888B8D";
const metal = createResource<DecimalSource>(0, "metal ingots", undefined, true);
const bestMetal = trackBest(metal);
const ore = createResource<DecimalSource>(0, "ore");
const bestOre = trackBest(ore);
const orePurity = createSequentialModifier(() => [
createMultiplicativeModifier(() => ({
multiplier: 5,
description: "Crucible",
enabled: crucible.bought
})),
createMultiplicativeModifier(() => ({
multiplier: 2,
description: "Industrial Furnace",
enabled: industrialFurnace.bought
})),
createMultiplicativeModifier(() => ({
multiplier: () => Decimal.add(hotterForgeEffect.value, 1),
description: "Hotter Forges",
enabled: () => Decimal.gte(hotterForge.amount.value, 1)
}))
]);
const computedOrePurity = computed(() => orePurity.apply(0.1));
const autoSmeltSpeed = createSequentialModifier(() => [
createAdditiveModifier(() => ({
addend: () => Decimal.times(industrialCrucible.amount.value, 10),
description: "Industrial Crucibles",
enabled: () => Decimal.gte(industrialCrucible.amount.value, 1)
}))
]);
const computedAutoSmeltSpeed = computed(() => autoSmeltSpeed.apply(0));
const coalCost = 1e10;
const smeltableOre = computed(() =>
Decimal.min(
ore.value,
Decimal.div(coal.coal.value, coalCost)
).floor().max(0)
);
const smeltOreButton = createClickable(() => ({
display: jsx(() => {
const cost = Decimal.gte(smeltableOre.value, 1)
? smeltableOre.value
: Decimal.add(smeltableOre.value, 1);
return (
<>
<span style="font-size: large">
Smelt {format(Decimal.times(smeltableOre.value, computedOrePurity.value))} {metal.displayName}
</span><br />
<span style="font-size: large">
Cost: {formatWhole(cost)} {ore.displayName}; {formatWhole(Decimal.times(cost, coalCost))} {coal.coal.displayName}
</span>
</>
)
}),
canClick: () => Decimal.gte(smeltableOre.value, 1),
onClick() {
if (!unref(this.canClick)) return;
smeltOre(smeltableOre.value);
},
style: {
width: "600px",
minHeight: "unset"
}
}));
function smeltOre(amount: DecimalSource) {
let [metalGain, oreConsumption, coalConsumption] = [
Decimal.times(amount, computedOrePurity.value),
amount,
Decimal.times(amount, coalCost)
];
metal.value = Decimal.add(metal.value, metalGain);
ore.value = Decimal.sub(ore.value, oreConsumption);
coal.coal.value = Decimal.sub(coal.coal.value, coalConsumption);
}
const oreAmount = createSequentialModifier(() => [
createAdditiveModifier(() => ({
addend: () => oreDrill.amount.value,
description: "Mining Drills",
enabled: () => Decimal.gte(oreDrill.amount.value, 1)
}))
]);
const computedOreAmount = computed(() => oreAmount.apply(1));
const oreSpeed = createSequentialModifier(() => [
createMultiplicativeModifier(() => ({
multiplier: 2,
description: "A Simple Pickaxe",
enabled: simplePickaxe.bought
})),
createMultiplicativeModifier(() => ({
multiplier: 2,
description: "Double Pickaxe",
enabled: doublePickaxe.bought
})),
createMultiplicativeModifier(() => ({
multiplier: 2.5,
description: "Mining Drills",
enabled: () => Decimal.gte(oreDrill.amount.value, 1)
}))
]);
const computedOreSpeed = computed(() => oreSpeed.apply(1));
const oreProgress = persistent<DecimalSource>(0);
const maxOreProgress = 10;
const oreBar = createBar(() => ({
width: 400,
height: 25,
direction: Direction.Right,
fillStyle: { backgroundColor: color },
progress: () => Decimal.div(oreProgress.value, maxOreProgress)
}));
const metalGain = createSequentialModifier(() => [
createAdditiveModifier(() => ({
addend: computedAutoSmeltSpeed,
enabled: autoSmeltEnabled
})),
createMultiplicativeModifier(() => ({
multiplier: computedOrePurity
}))
]);
const computedMetalGain = computed(() => metalGain.apply(0));
const oreGain = createSequentialModifier(() => [
createAdditiveModifier(() => ({
addend: computedOreAmount
})),
createMultiplicativeModifier(() => ({
multiplier: computedOreSpeed
})),
createMultiplicativeModifier(() => ({
multiplier: Decimal.reciprocate(maxOreProgress)
}))
])
const computedOreGain = computed(() => oreGain.apply(0));
const netOreGain = createSequentialModifier(() => [
createAdditiveModifier(() => ({
addend: computedOreGain
})),
createAdditiveModifier(() => ({
addend: () => Decimal.negate(computedAutoSmeltSpeed.value),
enabled: autoSmeltEnabled
}))
])
const computedNetOreGain = computed(() => netOreGain.apply(0));
const simplePickaxe = createUpgrade(() => ({
resource: noPersist(metal),
cost: 0.1,
display: {
title: "A Simple Pickaxe",
description: "Make a simple pickaxe to help mine faster.<br/><br/>Halve the time to mine more ore"
}
}));
const doublePickaxe = createUpgrade(() => ({
resource: noPersist(metal),
cost: 0.1,
display: {
title: "Double Pickaxe",
description: "This is too slow. What if you swung two pickaxes at once?<br/><br/>Halve the time to mine ore, again"
},
visibility: () => showIf(doublePickaxe.bought.value)
})) as GenericUpgrade;
const crucible = createUpgrade(() => ({
resource: noPersist(metal),
cost: 1,
display: {
title: "Crucible",
description: "Smelting this all by hand is rather painful, and a lot of the metal is left in the slag. A small crucible should help a lot!<br/><br/>Increase the metal extracted per ore by 5x"
},
visibility: () => showIf(crucible.bought.value || Decimal.div(bestOre.value, computedOrePurity.value).plus(bestMetal.value).gte(1))
})) as GenericUpgrade;
const coalDrill = createUpgrade(() => ({
resource: noPersist(metal),
cost: 0,
display: {
title: "Coal Drilling",
description: "These mining drills are pretty powerful, mining more ore than you can actually smelt. Could be worth making some to mine coal instead"
},
visibility: () => showIf(Decimal.gte(oreDrill.amount.value, 1) && (
coalDrill.bought.value ||
Decimal.lt(coal.computedCoalGain.value, Decimal.times(computedOreAmount.value, computedOreSpeed.value).div(maxOreProgress).times(coalCost))))
})) as GenericUpgrade;
const industrialFurnace = createUpgrade(() => ({
canAfford() {
return Decimal.gte(metal.value, 50) && Decimal.gte(coal.coal.value, 1e11)
},
onPurchase() {
metal.value = Decimal.sub(metal.value, 50);
coal.coal.value = Decimal.sub(coal.coal.value, 1e11);
},
display: {
title: "Industrial Furnace",
description: `Moving smelting out of the open air and into a dedicated furnace should make efficiency even better. Double metal gained per ore
<br/>
<br/>
Cost: 50 ${metal.displayName}<br/>${format(1e11)} ${coal.coal.displayName}`
}
}));
const oreDrill = createBuyable(() => ({
resource: noPersist(metal),
cost() { return Decimal.pow(this.amount.value, 1.15).plus(10)},
display: {
title: "Mining Drill",
description: "An automated machine to help you mine more ore, faster",
effectDisplay: jsx(() => <>Mine 2.5x faster. Increase ore mining amount by {formatWhole(oreDrill.amount.value)} ore per operation</>)
},
visibility: () => showIf(Decimal.gte(oreDrill.amount.value, 1) || Decimal.div(bestOre.value, computedOrePurity.value).plus(bestMetal.value).gte(10)),
style: { width: '200px' }
})) as GenericBuyable
const industrialCrucible = createBuyable(() => ({
resource: noPersist(metal),
cost() { return Decimal.pow(Decimal.times(this.amount.value, 10), 1.15).plus(10)},
display: {
title: "Industrial Crucible",
description: "A giant automated crucible furnace, letting you smelt ore better and faster",
effectDisplay: jsx(() => <>Get 50% more metal per ore, and smelt {formatWhole(Decimal.times(industrialCrucible.amount.value, 10))} ore per second</>)
},
visibility: () => showIf(Decimal.gte(industrialCrucible.amount.value, 1) || Decimal.gte(oreDrill.amount.value, 4) || Decimal.gte(bestOre.value, 50)),
style: { width: '200px' }
})) as GenericBuyable
const autoSmeltEnabled = persistent<boolean>(true);
const hotterForge = createBuyable(() => ({
resource: coal.coal,
cost() { return Decimal.pow(10, this.amount.value).times(1e12)},
display: {
title: "Hotter Forges",
description: "More coal makes the fires burn hotter, getting just a little more metal out of each bit of ore",
effectDisplay: jsx(() => <>Gain {formatWhole(Decimal.times(hotterForgeEffect.value, 100))}% more metal per ore</>)
},
visibility: () => showIf(Decimal.gte(hotterForge.amount.value, 1) || industrialFurnace.bought.value),
style: { width: '200px' }
})) as GenericBuyable;
const hotterForgeEffect = computed(() => Decimal.times(hotterForge.amount.value, 0.25));
globalBus.on("update", diff => {
oreProgress.value = Decimal.times(diff, computedOreSpeed.value).plus(oreProgress.value);
const oreGain = oreProgress.value.div(maxOreProgress).trunc();
oreProgress.value = oreProgress.value.minus(oreGain.times(maxOreProgress));
ore.value = Decimal.add(ore.value, oreGain);
if (autoSmeltEnabled.value && Decimal.gte(smeltableOre.value, Decimal.times(industrialCrucible.amount.value, 10).times(diff))) {
smeltOre(Decimal.min(
smeltableOre.value,
Decimal.times(industrialCrucible.amount.value, 10).times(diff)
));
}
});
const [generalTab, generalTabCollapsed] = createCollapsibleModifierSections(() => [
{
title: "Automatic Smelting",
modifier: autoSmeltSpeed,
base: 0,
visible() {
return Decimal.gt(industrialCrucible.amount.value, 0);
}
},
{
title: "Metal per Ore",
modifier: orePurity,
base: 0.1
},
{
title: "Ore per Mining Operation",
modifier: oreAmount,
base: 1
},
{
title: "Mining Speed",
modifier: oreSpeed,
base: 1
}
]);
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
}}
/>
));
const { total: totalMetal, trackerDisplay } = setUpDailyProgressTracker({
resource: metal,
goal: 5000,
name,
day,
color,
modal: {
show: showModifiersModal,
display: modifiersModal
}
});
return {
name,
day,
color,
ore,
bestOre,
oreProgress,
metal,
bestMetal,
totalMetal,
simplePickaxe,
doublePickaxe,
crucible,
coalDrill,
industrialFurnace,
oreDrill,
industrialCrucible,
autoSmeltEnabled,
hotterForge,
minWidth: 700,
display: jsx(() => (
<>
{render(trackerDisplay)}
<Spacer />
<MainDisplay resource={metal} color={color} style="margin-bottom: 0" sticky={false}
productionDisplay={
<>{{
[-1]: <>{format(computedMetalGain.value)}/s</>,
0: undefined,
1: <>+{format(computedMetalGain.value)}/s</>
}[Decimal.compare(computedMetalGain.value, 0)]}</>
}
/>
<Spacer />
{render(smeltOreButton)}
{Decimal.gte(industrialCrucible.amount.value, 1)
? <div style={{width: '150px'}}>
<Toggle title="Auto Smelt" modelValue={autoSmeltEnabled.value} onUpdate:modelValue={value => (autoSmeltEnabled.value = value)}/>
</div>
: undefined}
<Spacer />
<MainDisplay resource={ore} color={color} style="margin-bottom: 0" sticky={false}
productionDisplay={
<>{{
[-1]: <>{format(computedNetOreGain.value)}/s</>,
0: undefined,
1: <>+{format(computedNetOreGain.value)}/s</>
}[Decimal.compare(computedNetOreGain.value, 0)]}</>
}
/>
<Spacer />
<div>
Currently mining {format(computedOreAmount.value)} ore every {format(Decimal.div(maxOreProgress, computedOreSpeed.value))} seconds
</div>
{render(oreBar)}
<Spacer />
{renderRow(simplePickaxe, doublePickaxe, crucible, coalDrill, industrialFurnace)}
{renderRow(oreDrill, industrialCrucible, hotterForge)}
</>
))
}
});
export default layer;

View file

@ -26,10 +26,12 @@ import coalSymbol from "./symbols/coal.png";
import elfSymbol from "./symbols/elf.png";
import paperSymbol from "./symbols/paperStacks.png";
import boxesSymbol from "./symbols/cardboardBox.png";
import metalSymbol from "./symbols/metal.png";
import coal from "./layers/coal";
import elves from "./layers/elves";
import paper from "./layers/paper";
import boxes from "./layers/boxes";
import metal from "./layers/metal";
export interface Day extends VueFeature {
day: number;
@ -198,15 +200,15 @@ export const main = createLayer("main", function (this: BaseLayer) {
createDay(() => ({
day: 7,
shouldNotify: false,
layer: null,
symbol: "",
layer: "metal",
symbol: metalSymbol,
story: "",
completedStory: ""
})),
createDay(() => ({
day: 8,
shouldNotify: false,
layer: null,
layer: null, // "cloth"
symbol: "",
story: "",
completedStory: ""
@ -214,7 +216,7 @@ export const main = createLayer("main", function (this: BaseLayer) {
createDay(() => ({
day: 9,
shouldNotify: false,
layer: null,
layer: null, // "oil"
symbol: "",
story: "",
completedStory: ""
@ -222,7 +224,7 @@ export const main = createLayer("main", function (this: BaseLayer) {
createDay(() => ({
day: 10,
shouldNotify: false,
layer: null,
layer: null, // "plastic"
symbol: "",
story: "",
completedStory: ""
@ -230,7 +232,7 @@ export const main = createLayer("main", function (this: BaseLayer) {
createDay(() => ({
day: 11,
shouldNotify: false,
layer: null,
layer: null, // "dyes"
symbol: "",
story: "",
completedStory: ""
@ -238,7 +240,7 @@ export const main = createLayer("main", function (this: BaseLayer) {
createDay(() => ({
day: 12,
shouldNotify: false,
layer: null,
layer: null, // "management"
symbol: "",
story: "",
completedStory: ""
@ -246,7 +248,7 @@ export const main = createLayer("main", function (this: BaseLayer) {
createDay(() => ({
day: 13,
shouldNotify: false,
layer: null,
layer: null, // ""
symbol: "",
story: "",
completedStory: ""
@ -254,7 +256,7 @@ export const main = createLayer("main", function (this: BaseLayer) {
createDay(() => ({
day: 14,
shouldNotify: false,
layer: null,
layer: null, // ""
symbol: "",
story: "",
completedStory: ""
@ -262,7 +264,7 @@ export const main = createLayer("main", function (this: BaseLayer) {
createDay(() => ({
day: 15,
shouldNotify: false,
layer: null,
layer: null, // "wrapping paper"
symbol: "",
story: "",
completedStory: ""
@ -270,7 +272,7 @@ export const main = createLayer("main", function (this: BaseLayer) {
createDay(() => ({
day: 16,
shouldNotify: false,
layer: null,
layer: null, // "ribbons"
symbol: "",
story: "",
completedStory: ""
@ -278,7 +280,7 @@ export const main = createLayer("main", function (this: BaseLayer) {
createDay(() => ({
day: 17,
shouldNotify: false,
layer: null,
layer: null, // "toys 1"
symbol: "",
story: "",
completedStory: ""
@ -286,7 +288,7 @@ export const main = createLayer("main", function (this: BaseLayer) {
createDay(() => ({
day: 18,
shouldNotify: false,
layer: null,
layer: null, // "toys 2"
symbol: "",
story: "",
completedStory: ""
@ -294,7 +296,7 @@ export const main = createLayer("main", function (this: BaseLayer) {
createDay(() => ({
day: 19,
shouldNotify: false,
layer: null,
layer: null, // "toys 3"
symbol: "",
story: "",
completedStory: ""
@ -302,7 +304,7 @@ export const main = createLayer("main", function (this: BaseLayer) {
createDay(() => ({
day: 20,
shouldNotify: false,
layer: null,
layer: null, // "presents"
symbol: "",
story: "",
completedStory: ""
@ -310,7 +312,7 @@ export const main = createLayer("main", function (this: BaseLayer) {
createDay(() => ({
day: 21,
shouldNotify: false,
layer: null,
layer: null, // "reindeer"
symbol: "",
story: "",
completedStory: ""
@ -318,7 +320,7 @@ export const main = createLayer("main", function (this: BaseLayer) {
createDay(() => ({
day: 22,
shouldNotify: false,
layer: null,
layer: null, // "sleigh"
symbol: "",
story: "",
completedStory: ""
@ -326,7 +328,7 @@ export const main = createLayer("main", function (this: BaseLayer) {
createDay(() => ({
day: 23,
shouldNotify: false,
layer: null,
layer: null, // "distribution route planning"
symbol: "",
story: "",
completedStory: ""
@ -334,7 +336,7 @@ export const main = createLayer("main", function (this: BaseLayer) {
createDay(() => ({
day: 24,
shouldNotify: false,
layer: null,
layer: null, // "packing the presents"
symbol: "",
story: "",
completedStory: ""
@ -398,7 +400,7 @@ export const main = createLayer("main", function (this: BaseLayer) {
export const getInitialLayers = (
/* eslint-disable-next-line @typescript-eslint/no-unused-vars */
player: Partial<PlayerData>
): Array<GenericLayer> => [main, trees, workshop, coal, elves, paper, boxes];
): Array<GenericLayer> => [main, trees, workshop, coal, elves, paper, boxes, metal];
/**
* A computed ref whose value is true whenever the game is over.

BIN
src/data/symbols/metal.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

View file

@ -1,5 +1,5 @@
<template>
<Sticky>
<Sticky v-if="sticky">
<div
class="main-display-container"
:class="classes ?? {}"
@ -20,6 +20,25 @@
</div>
</div>
</Sticky>
<div v-else
class="main-display-container"
:class="classes ?? {}"
:style="[{ height: '50px' }, style ?? {}]"
>
<div class="main-display">
<span v-if="showPrefix">You have </span>
<ResourceVue :resource="resource" :color="color || 'white'" />
{{ resource.displayName
}}<!-- remove whitespace -->
<span v-if="effectComponent"
>, <component :is="effectComponent" ref="effectRef"
/></span>
<span v-if="productionComponent">
<br />
<component :is="productionComponent" ref="effectRef"
/></span>
</div>
</div>
</template>
<script setup lang="ts">
@ -32,14 +51,15 @@ import { computeOptionalComponent } from "util/vue";
import { ComponentPublicInstance, ref, Ref, StyleValue } from "vue";
import { computed, toRefs } from "vue";
const _props = defineProps<{
const _props = withDefaults(defineProps<{
resource: Resource;
color?: string;
classes?: Record<string, boolean>;
style?: StyleValue;
effectDisplay?: CoercableComponent;
productionDisplay?: CoercableComponent;
}>();
sticky?: boolean
}>(), {sticky: true});
const props = toRefs(_props);
const effectRef = ref<ComponentPublicInstance | null>(null);