diff --git a/src/assets/fonts.css b/src/assets/fonts.css index 4c8a2af..af92ad8 100644 --- a/src/assets/fonts.css +++ b/src/assets/fonts.css @@ -95,4 +95,9 @@ @font-face { font-family: NikoTamagotchi; src: url('fonts/NikoTamagotchi.ttf') format('truetype'); -} \ No newline at end of file +} + +@font-face { + font-family: Merriweather; + src: url('fonts/Merriweather-Black.ttf') format('woff2'); +} diff --git a/src/assets/fonts/Merriweather-Black.ttf b/src/assets/fonts/Merriweather-Black.ttf new file mode 100644 index 0000000..50c3b33 Binary files /dev/null and b/src/assets/fonts/Merriweather-Black.ttf differ diff --git a/src/channels/cookie-clicker/assets/bgAntim.png b/src/channels/cookie-clicker/assets/bgAntim.png new file mode 100644 index 0000000..ae90cb6 Binary files /dev/null and b/src/channels/cookie-clicker/assets/bgAntim.png differ diff --git a/src/channels/cookie-clicker/assets/bgBank.png b/src/channels/cookie-clicker/assets/bgBank.png new file mode 100644 index 0000000..4d23283 Binary files /dev/null and b/src/channels/cookie-clicker/assets/bgBank.png differ diff --git a/src/channels/cookie-clicker/assets/bgBlue.png b/src/channels/cookie-clicker/assets/bgBlue.png new file mode 100644 index 0000000..b568f07 Binary files /dev/null and b/src/channels/cookie-clicker/assets/bgBlue.png differ diff --git a/src/channels/cookie-clicker/assets/bgChance.png b/src/channels/cookie-clicker/assets/bgChance.png new file mode 100644 index 0000000..64b9869 Binary files /dev/null and b/src/channels/cookie-clicker/assets/bgChance.png differ diff --git a/src/channels/cookie-clicker/assets/bgCortex.png b/src/channels/cookie-clicker/assets/bgCortex.png new file mode 100644 index 0000000..6203264 Binary files /dev/null and b/src/channels/cookie-clicker/assets/bgCortex.png differ diff --git a/src/channels/cookie-clicker/assets/bgFactory.png b/src/channels/cookie-clicker/assets/bgFactory.png new file mode 100644 index 0000000..e96ea55 Binary files /dev/null and b/src/channels/cookie-clicker/assets/bgFactory.png differ diff --git a/src/channels/cookie-clicker/assets/bgFarm.png b/src/channels/cookie-clicker/assets/bgFarm.png new file mode 100644 index 0000000..fe6acf9 Binary files /dev/null and b/src/channels/cookie-clicker/assets/bgFarm.png differ diff --git a/src/channels/cookie-clicker/assets/bgFractal.png b/src/channels/cookie-clicker/assets/bgFractal.png new file mode 100644 index 0000000..f0dda75 Binary files /dev/null and b/src/channels/cookie-clicker/assets/bgFractal.png differ diff --git a/src/channels/cookie-clicker/assets/bgGrandma.png b/src/channels/cookie-clicker/assets/bgGrandma.png new file mode 100644 index 0000000..dba0b3d Binary files /dev/null and b/src/channels/cookie-clicker/assets/bgGrandma.png differ diff --git a/src/channels/cookie-clicker/assets/bgIdle.png b/src/channels/cookie-clicker/assets/bgIdle.png new file mode 100644 index 0000000..ee81b27 Binary files /dev/null and b/src/channels/cookie-clicker/assets/bgIdle.png differ diff --git a/src/channels/cookie-clicker/assets/bgJava.png b/src/channels/cookie-clicker/assets/bgJava.png new file mode 100644 index 0000000..f5fdf9e Binary files /dev/null and b/src/channels/cookie-clicker/assets/bgJava.png differ diff --git a/src/channels/cookie-clicker/assets/bgLab.png b/src/channels/cookie-clicker/assets/bgLab.png new file mode 100644 index 0000000..2cd0cce Binary files /dev/null and b/src/channels/cookie-clicker/assets/bgLab.png differ diff --git a/src/channels/cookie-clicker/assets/bgMine.png b/src/channels/cookie-clicker/assets/bgMine.png new file mode 100644 index 0000000..7986c4c Binary files /dev/null and b/src/channels/cookie-clicker/assets/bgMine.png differ diff --git a/src/channels/cookie-clicker/assets/bgPortal.png b/src/channels/cookie-clicker/assets/bgPortal.png new file mode 100644 index 0000000..441de2a Binary files /dev/null and b/src/channels/cookie-clicker/assets/bgPortal.png differ diff --git a/src/channels/cookie-clicker/assets/bgPrism.png b/src/channels/cookie-clicker/assets/bgPrism.png new file mode 100644 index 0000000..ecb4eb5 Binary files /dev/null and b/src/channels/cookie-clicker/assets/bgPrism.png differ diff --git a/src/channels/cookie-clicker/assets/bgShipment.png b/src/channels/cookie-clicker/assets/bgShipment.png new file mode 100644 index 0000000..210c66a Binary files /dev/null and b/src/channels/cookie-clicker/assets/bgShipment.png differ diff --git a/src/channels/cookie-clicker/assets/bgTemple.png b/src/channels/cookie-clicker/assets/bgTemple.png new file mode 100644 index 0000000..613917e Binary files /dev/null and b/src/channels/cookie-clicker/assets/bgTemple.png differ diff --git a/src/channels/cookie-clicker/assets/bgTime.png b/src/channels/cookie-clicker/assets/bgTime.png new file mode 100644 index 0000000..01b50a2 Binary files /dev/null and b/src/channels/cookie-clicker/assets/bgTime.png differ diff --git a/src/channels/cookie-clicker/assets/bgTower.png b/src/channels/cookie-clicker/assets/bgTower.png new file mode 100644 index 0000000..e8cfeb4 Binary files /dev/null and b/src/channels/cookie-clicker/assets/bgTower.png differ diff --git a/src/channels/cookie-clicker/assets/buildingIcons.png b/src/channels/cookie-clicker/assets/buildingIcons.png new file mode 100644 index 0000000..6eade83 Binary files /dev/null and b/src/channels/cookie-clicker/assets/buildingIcons.png differ diff --git a/src/channels/cookie-clicker/assets/cookieParticle.png b/src/channels/cookie-clicker/assets/cookieParticle.png new file mode 100644 index 0000000..8eb9c40 Binary files /dev/null and b/src/channels/cookie-clicker/assets/cookieParticle.png differ diff --git a/src/channels/cookie-clicker/assets/cookieShadow.png b/src/channels/cookie-clicker/assets/cookieShadow.png new file mode 100644 index 0000000..5a8bf6f Binary files /dev/null and b/src/channels/cookie-clicker/assets/cookieShadow.png differ diff --git a/src/channels/cookie-clicker/assets/cursor.png b/src/channels/cookie-clicker/assets/cursor.png new file mode 100644 index 0000000..d111303 Binary files /dev/null and b/src/channels/cookie-clicker/assets/cursor.png differ diff --git a/src/channels/cookie-clicker/assets/panelHorizontal.png b/src/channels/cookie-clicker/assets/panelHorizontal.png new file mode 100644 index 0000000..95d4cb1 Binary files /dev/null and b/src/channels/cookie-clicker/assets/panelHorizontal.png differ diff --git a/src/channels/cookie-clicker/assets/panelVertical.png b/src/channels/cookie-clicker/assets/panelVertical.png new file mode 100644 index 0000000..7bcccca Binary files /dev/null and b/src/channels/cookie-clicker/assets/panelVertical.png differ diff --git a/src/channels/cookie-clicker/assets/perfectCookie.png b/src/channels/cookie-clicker/assets/perfectCookie.png new file mode 100644 index 0000000..bc6282c Binary files /dev/null and b/src/channels/cookie-clicker/assets/perfectCookie.png differ diff --git a/src/channels/cookie-clicker/assets/shadedBordersSoft.png b/src/channels/cookie-clicker/assets/shadedBordersSoft.png new file mode 100644 index 0000000..224a022 Binary files /dev/null and b/src/channels/cookie-clicker/assets/shadedBordersSoft.png differ diff --git a/src/channels/cookie-clicker/assets/shine.png b/src/channels/cookie-clicker/assets/shine.png new file mode 100644 index 0000000..f48e14a Binary files /dev/null and b/src/channels/cookie-clicker/assets/shine.png differ diff --git a/src/channels/cookie-clicker/assets/storeTile.png b/src/channels/cookie-clicker/assets/storeTile.png new file mode 100644 index 0000000..5590ce9 Binary files /dev/null and b/src/channels/cookie-clicker/assets/storeTile.png differ diff --git a/src/channels/cookie-clicker/buildings.tsx b/src/channels/cookie-clicker/buildings.tsx new file mode 100644 index 0000000..ec5aaf9 --- /dev/null +++ b/src/channels/cookie-clicker/buildings.tsx @@ -0,0 +1,210 @@ +import grandmaBackground from './assets/bgGrandma.png'; +import farmBackground from './assets/bgFarm.png'; +import mineBackground from './assets/bgMine.png'; +import factoryBackground from './assets/bgFactory.png'; +import bankBackground from './assets/bgBank.png'; +import templeBackground from './assets/bgTemple.png'; +import towerBackground from './assets/bgTower.png'; +import shipmentBackground from './assets/bgShipment.png'; +import labBackground from './assets/bgLab.png'; +import portalBackground from './assets/bgPortal.png'; +import timeBackground from './assets/bgTime.png'; +import antimBackground from './assets/bgAntim.png'; +import prismBackground from './assets/bgPrism.png'; +import { RefObject } from 'react'; + +export type Building = { + index: number; // gives location of building on sprite sheets + name: string; + total: number; + price: number; + background: string; + canvasRef: null | RefObject; + savedCanvas: undefined | ImageData; + storeRef: null | RefObject; + yRandomization: number; +}; + +// let cursor: Building = { +// index: 0, +// name: "Cursor", +// total: 0, +// price: 1, +// background: "", +// canvasRef: null, +// savedCanvas: null, +// storeRef: null, +// yRandomization: 0, +// } + +const grandma: Building = { + index: 1, + name: 'Grandma', + total: 0, + price: 1, + background: grandmaBackground, + canvasRef: null, + savedCanvas: undefined, + storeRef: null, + yRandomization: 10, +}; + +const farm: Building = { + index: 2, + name: 'Farm', + total: 0, + price: 5, + background: farmBackground, + canvasRef: null, + savedCanvas: undefined, + storeRef: null, + yRandomization: 8, +}; + +const mine: Building = { + index: 3, + name: 'Mine', + total: 0, + price: 10, + background: mineBackground, + canvasRef: null, + savedCanvas: undefined, + storeRef: null, + yRandomization: 8, +}; + +const factory: Building = { + index: 4, + name: 'Factory', + total: 0, + price: 15, + background: factoryBackground, + canvasRef: null, + savedCanvas: undefined, + storeRef: null, + yRandomization: 0, +}; + +const bank: Building = { + index: 5, + name: 'Bank', + total: 0, + price: 30, + background: bankBackground, + canvasRef: null, + savedCanvas: undefined, + storeRef: null, + yRandomization: 4, +}; + +const temple: Building = { + index: 6, + name: 'Temple', + total: 0, + price: 50, + background: templeBackground, + canvasRef: null, + savedCanvas: undefined, + storeRef: null, + yRandomization: 2, +}; + +const tower: Building = { + index: 7, + name: 'Wizard Tower', + total: 0, + price: 75, + background: towerBackground, + canvasRef: null, + savedCanvas: undefined, + storeRef: null, + yRandomization: 5, +}; + +const shipment: Building = { + index: 8, + name: 'Shipment', + total: 0, + price: 100, + background: shipmentBackground, + canvasRef: null, + savedCanvas: undefined, + storeRef: null, + yRandomization: 3, +}; + +const lab: Building = { + index: 9, + name: 'Alchemy Lab', + total: 0, + price: 125, + background: labBackground, + canvasRef: null, + savedCanvas: undefined, + storeRef: null, + yRandomization: 4, +}; + +const portal: Building = { + index: 10, + name: 'Portal', + total: 0, + price: 150, + background: portalBackground, + canvasRef: null, + savedCanvas: undefined, + storeRef: null, + yRandomization: 4, +}; + +const timeMachine: Building = { + index: 11, + name: 'Time Machine', + total: 0, + price: 175, + background: timeBackground, + canvasRef: null, + savedCanvas: undefined, + storeRef: null, + yRandomization: 5, +}; + +const antimCondenser: Building = { + index: 12, + name: 'Antimatter', + total: 0, + price: 200, + background: antimBackground, + canvasRef: null, + savedCanvas: undefined, + storeRef: null, + yRandomization: 8, +}; + +const prism: Building = { + index: 13, + name: 'Prism', + total: 0, + price: 250, + background: prismBackground, + canvasRef: null, + savedCanvas: undefined, + storeRef: null, + yRandomization: 1, +}; + +export const buildings = [ + grandma, + farm, + mine, + factory, + bank, + temple, + tower, + shipment, + lab, + portal, + timeMachine, + antimCondenser, + prism, +]; diff --git a/src/channels/cookie-clicker/components.tsx b/src/channels/cookie-clicker/components.tsx new file mode 100644 index 0000000..357e1ef --- /dev/null +++ b/src/channels/cookie-clicker/components.tsx @@ -0,0 +1,338 @@ +import { useRef, FC } from 'react'; +import { css, keyframes } from '@emotion/react'; +import styled from '@emotion/styled'; +import { Building } from './buildings'; +import { random } from 'lodash'; + +// images +import background from './assets/bgBlue.png'; +import vignette from './assets/shadedBordersSoft.png'; +import panelVertical from './assets/panelVertical.png'; +import panelHorizontal from './assets/panelHorizontal.png'; +import cookieGlow from './assets/shine.png'; +import cookieShadow from './assets/cookieShadow.png'; +import perfectCookie from './assets/perfectCookie.png'; +import cookieParticle from './assets/cookieParticle.png'; + +// sprite sheets +import storeBackground from './assets/storeTile.png'; +import buildingIcons from './assets/buildingIcons.png'; + +export const BuildingSection: FC<{ buildingObject: Building }> = ({ buildingObject }) => { + buildingObject.canvasRef = useRef(null); + + // pasting saved building canvas + const context = buildingObject.canvasRef.current?.getContext('2d'); + if (buildingObject.savedCanvas) context?.putImageData(buildingObject.savedCanvas, 0, 0); + + return ( + <> + + + ); +}; + +export const StoreSection: FC<{ buildingObject: Building }> = ({ buildingObject }) => { + buildingObject.storeRef = useRef(null); + + return ( + <> +
+
+ + {buildingObject.total} + {buildingObject.name} + > ${buildingObject.price} Donation + +
+ + ); +}; + +const HorizontalSection = css` + position: relative; + image-rendering: pixelated; + vertical-align: top; + border-image: url('${panelHorizontal}') 16 round; + border-bottom-width: 16px; + border-bottom-style: solid; + width: 110%; + height: 128px; +`; +const Store = styled.div` + position: absolute; + top: 9px; + font-size: 95%; + text-align: left; + right: 2.5%; + width: calc(100% - 64px); +`; + +const StoreWindow = css` + position: relative; + vertical-align: top; + width: 100%; + height: 64px; + + background: ; +`; + +const StoreIcon = css` + position absolute; + image-rendering: pixelated; + left: 0; + width: 64px; + height: 64px; + filter: drop-shadow(0 0 5px black); +`; + +const TotalText = styled.div` + position: absolute; + text-align: right; + font-size: 230%; + right: 0; + width: 100%; + color: black; + opacity: 0.4; +`; + +const Price = styled.div` + position: absolute; + text-shadow: 0px 1px 3px black; + text-align: left; + color: #66ff66; + font-size: 45%; + right: 2.5%; + top: 32px; + width: calc(100% - 64px); +`; + +export function ParticleAnimation(locationX: number, locationY: number) { + const flipped = random(0, 1) == 0 ? 1 : -1; + + return keyframes` + from{ + left: ${locationX}%; + top: ${locationY}%; + transform: rotate(0); + opacity: 1; + } + 20%{ + left: ${locationX + 1 * flipped}%; + top: ${locationY - 2}%; + transform: rotate(5deg); + opacity: 0.8; + } + 40%{ + left: ${locationX + 2.5 * flipped}%; + top: ${locationY - 3}%; + transform: rotate(10deg); + opacity: 0.6; + } + 60%{ + left: ${locationX + 4 * flipped}%; + top: ${locationY - 2}%; + transform: rotate(15deg); + opacity: 0.4; + } + 80%{ + left: ${locationX + 5 * flipped}%; + top: ${locationY}%; + transform: rotate(20deg); + opacity: 0.2; + } + 100%:{ + left: ${locationX + 6 * flipped}%; + top: ${locationY + 3}% + transform: rotate(20deg); + opacity: 0; + }`; +} + +export const FadeUpAnimation = (locationY: number) => { + return keyframes` + from{ + top: ${locationY}%; + opacity: 1; + } + to{ + top: ${locationY - 10}%; + opacity: 0; + }`; +}; + +export const FloatText = (locationX: number) => { + return css` + position: absolute; + font-family: Merriweather; + font-size: 100%; + text-shadow: 0px 1px 5px black; + left: ${locationX + '%'}; + `; +}; + +export const CookieClicked = keyframes` + from{ + transform: scale(1) + } + 15%{ + transform: scale(0.9) + } + 25%{ + transform: scale(1) + } + 65%{ + transform: scale(0.95) + } + to{ + transform: scale(1) + } +`; + +export const staticFadeUp = keyframes` + from{ + top: 25%; + opacity: 1; + } + 90%{ + top: 25%; + opacity: 1; + } + to{ + top: 0%; + opacity: 0; + } +`; + +export const CookieParticle = styled.img` + position: absolute; + content: url(${cookieParticle}); + image-rendering: pixelated; +`; + +export const Container = styled.div` + position: absolute; + background: url('${background}'); + background-repeat: repeat; + width: 100%; + height: 100%; +`; + +export const VerticalSection = styled.div` + position: absolute; + background: url('${vignette}'); + border-image: url('${panelVertical}') 16 round; + border-right-width: 16px; + border-right-style: solid; + width: 30%; + height: 100%; + background-size: 100% 100%; + background-repeat: no-repeat; + overflow-y: hidden; + overflow-x: hidden; +`; + +export const Cookie = styled.div` + position: absolute; + top: 5%; + width: 100%; + height: 100%; + + background: url(${perfectCookie}), url(${cookieShadow}); + background-size: 70% 70%, 85% 85%; + background-repeat: no-repeat, no-repeat; + background-position: center, center; +`; + +export const CookieGlow = styled.div` + position: absolute; + top: 55%; + left: 50%; + width: 100%; + height: 100%; + + transform-origin: center; + background: url(${cookieGlow}); + background-repeat: no-repeat; + background-size: 100% 100%; + background-position: center; + + animation-name: rotate; + animation-duration: 10s; + animation-timing-function: linear; + animation-iteration-count: infinite; + @keyframes rotate { + from { + transform: translate(-50%, -50%) rotate(0deg); + } + to { + transform: translate(-50%, -50%) rotate(360deg); + } + } +`; + +export const AnnouncementSection = styled.div` + position: sticky; + top: 0; + z-index: 1; + display: flex; + justify-content: center; + align-items: center; + + background: url('${vignette}'), url('${background}'); + background-size: 100% 100%, 50% 50%; + background-repeat: no-repeat, repeat; + + border-image: url('${panelHorizontal}') 16 round; + border-bottom-width: 16px; + border-bottom-style: solid; + width: 100%; + height: 20%; +`; + +export const FormattedText = styled.div` + position: absolute; + font-family: Merriweather; + font-size: 150%; + text-align: center; + text-shadow: 0px 1px 5px black; + width: 100%; + top: 5%; + + & > small { + position: relative; + vertical-align: top; + color: #66ff66; + line-height: 1.5; + font-size: 45%; + } +`; + +export const AnnouncementText = styled.div` + position: absolute; + font-family: Merriweather; + font-size: 100%; + text-align: center; + text-shadow: 5px 5px 8px black; + width: 100%; + top: 25%; + margin: 0px 10px 10px 10px; +`; diff --git a/src/channels/cookie-clicker/index.tsx b/src/channels/cookie-clicker/index.tsx new file mode 100644 index 0000000..4dcbcee --- /dev/null +++ b/src/channels/cookie-clicker/index.tsx @@ -0,0 +1,220 @@ +import { useRef, useState } from 'react'; +import { css } from '@emotion/react'; +import TweenNumber from '@gdq/lib/components/TweenNumber'; +import { random } from 'lodash'; +import { ChannelProps, registerChannel } from '../channels'; +import { useListenFor, useReplicant } from 'use-nodecg'; +import type { Event, FormattedDonation, Total } from '@gdq/types/tracker'; + +// sprite sheets +import buildingIcons from './assets/buildingIcons.png'; +const htmlBuildingIcons = new Image(); +htmlBuildingIcons.src = `${buildingIcons}`; + +// local imports +import { buildings } from './buildings'; +import { + Container, + VerticalSection, + Cookie, + CookieGlow, + CookieParticle, + FloatText, + AnnouncementSection, + FormattedText, + AnnouncementText, + BuildingSection, + StoreSection, + ParticleAnimation, + FadeUpAnimation, + CookieClicked, + staticFadeUp, +} from './components'; +import { EmotionJSX } from '@emotion/react/types/jsx-namespace'; + +registerChannel('Cookie Clicker', 10, cookieClicker, { + position: 'bottomLeft', + handle: 'satasatalight', + site: 'GitHub', +}); + +let flavorText = [ + '"We\'re fast grandmas." - grandma', + 'Your cookies are popular at the venue.', + 'News: cookie factories on strike, TASBot employed to replace workforce!', + 'News: time machines involved in any% speedrunning scandal! Or are they?', + 'News: "explain to me again why we need particle accelerators to benefit charity?" asks misguided local woman.', + 'News: speedrunner forced to cancel Oreo sleeve 100% run after unrelated indigestion.', + 'News: "cookies helped me stay focused during my marathon runs" reveals runner.', +]; + +let usedFlavorText = Array(); +let sequentialKey = 0; // to give unique keys to array elements + +export function cookieClicker(props: ChannelProps) { + const [total] = useReplicant('total', null); + const currentEventRep = nodecg.Replicant('currentEvent'); + + const cookieRef = useRef(null); + const announcementRef = useRef(null); + const [announcementText, setAnnouncementText] = useState(''); + const [particles, setParticles] = useState>([]); + + // init announcement ticker + cssAnimate(announcementRef.current!); + + // donations + useListenFor('donation', (donation: FormattedDonation) => { + cssAnimate(cookieRef.current!); + drawBuilding(donation); + drawParticle(donation, setParticles); + }); + + //JSX + return ( + + {/* Big Cookie */} + + + + + + {particles} + + + + cookies +
+ to {currentEventRep.value?.beneficiary} +
+
+ + {/* Buildings */} + + + announcementTicker(setAnnouncementText)}> + {announcementText} + + + + {buildings.map((building) => { + return ; + })} + + + {/* Store */} + + {buildings.map((building) => { + return ; + })} + +
+ ); +} + +function announcementTicker(setText: Function) { + const announcementIndex = random(0, flavorText.length - 1); + setText(flavorText[announcementIndex]); + + usedFlavorText.push(flavorText[announcementIndex]); + flavorText.splice(announcementIndex, 1); + + if (flavorText.length == 0) { + flavorText = usedFlavorText; + usedFlavorText = Array(); + } +} + +function drawBuilding(donation: FormattedDonation) { + // buying building + for (let i = buildings.length - 1; i >= 0; i--) { + const building = buildings[i]; + + if (donation.rawAmount > building.price) { + const context = building.canvasRef?.current?.getContext('2d'); + + // drawing image by cropping out the building icon from the sprite sheet + // drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight) + context?.drawImage( + htmlBuildingIcons, + 128, + 64 * building.index, + 64, + 64, + (building.total % 10) * random(53, 60), + building.total % 2 == 0 + ? random(70 - building.yRandomization, 70) + : random(85 - building.yRandomization, 85), + 64, + 64, + ); + + building.savedCanvas = context?.getImageData( + 0, + 0, + building.canvasRef!.current!.width, + building.canvasRef!.current!.height, + ); + + building.total += 1; + + building.canvasRef?.current?.scrollIntoView({ block: 'end', behavior: 'smooth' }); + building.storeRef?.current?.scrollIntoView({ block: 'end', behavior: 'smooth' }); + break; + } + } +} + +function drawParticle(donation: FormattedDonation, setParticles: Function) { + const particleLocationX = random(15, 70); + const particleLocationY = random(35, 65); + + sequentialKey += 1; + + setParticles((prevParticles: Array) => [ + ...prevParticles, +
{ + removeParticle(setParticles); + }}> + + +
+ + {donation.amount} +
+
, + ]); +} + +function removeParticle(setParticles: Function) { + setParticles((prevParticles: Array) => prevParticles.slice(1, prevParticles.length)); +} + +function cssAnimate(element: HTMLElement) { + // mostly Copied from papers-please index.tsx + if (!element) return; + element.style.animation = 'none'; + element.offsetHeight; /* trigger reflow */ + element.style.removeProperty('animation'); +} diff --git a/src/channels/index.ts b/src/channels/index.ts index 74f2974..0544607 100644 --- a/src/channels/index.ts +++ b/src/channels/index.ts @@ -20,5 +20,6 @@ import './qwop'; import './laser-sunset'; import './here-comes-niko'; import './pinball'; +import './cookie-clicker'; export * from './channels';