Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create shopkeeper container #1062

Merged
merged 36 commits into from
Jan 7, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
7107ba0
Create initial shopkeeper container
maxwofford Dec 24, 2024
89322aa
New flavor & new yap. Handle intro messages
maxwofford Dec 24, 2024
b928c25
More flavor, more fun!
maxwofford Dec 24, 2024
9772443
Handle broken async process in yap.js
maxwofford Dec 24, 2024
44dfde8
Remove unused shopkeeper component
maxwofford Dec 24, 2024
7ec7e1e
Add self clicks and nonangry bell clicks
maxwofford Dec 24, 2024
7e9dd99
Format and add idle animation
maxwofford Dec 27, 2024
21c7523
Remove duplicated lines
maxwofford Dec 27, 2024
ffab3df
More flavor
maxwofford Dec 27, 2024
e944143
Add yaml loading to nextjs
maxwofford Dec 27, 2024
3bf0aa6
Switch to transcript system for shopkeeper
maxwofford Dec 27, 2024
6bad695
Improve shopkeeper text legibility
maxwofford Dec 27, 2024
00505ea
Add global event pub/sub for shopkeeper
maxwofford Dec 28, 2024
9784c91
New legal symbols in flavor text
maxwofford Dec 31, 2024
0fa4854
Higher chance for superstition generation
maxwofford Dec 31, 2024
8d3f878
Add emitYap helper
maxwofford Dec 31, 2024
1116adc
Turn off react strict mode in development
maxwofford Dec 31, 2024
2794a26
Bun fmt
maxwofford Dec 31, 2024
a26885d
Add flavor text to faving/unfaving items
maxwofford Dec 31, 2024
94f2ced
Add emitter unsubscribing in useEffect
maxwofford Dec 31, 2024
6fbc449
Add generic item interactions
maxwofford Dec 31, 2024
d701b0e
Add item specific lines for pinecil
maxwofford Dec 31, 2024
4f27a74
More self-click dialogue
maxwofford Dec 31, 2024
bd9d0e9
Another generic line
maxwofford Dec 31, 2024
2ea6e40
Add many new items flavor text
maxwofford Dec 31, 2024
8d4209f
Add speed to transcript system
maxwofford Dec 31, 2024
aa0918e
Delay sound response
maxwofford Jan 3, 2025
8e6bd59
Add more item lines
maxwofford Jan 3, 2025
13a4fd6
Fix up more missing flavor text and icons
maxwofford Jan 7, 2025
108b1d8
Fix up bapanada intro line
maxwofford Jan 7, 2025
4cac56a
Add further shopkeeper greeting instructions
maxwofford Jan 7, 2025
43a1115
Patch up generic flavor text
maxwofford Jan 7, 2025
b454842
Make trumpets clickable
maxwofford Jan 7, 2025
1e58ede
Center the bell
maxwofford Jan 7, 2025
8ad18fc
Merge branch 'main' into create-shopkeeper-container
maxwofford Jan 7, 2025
b540358
Run fmt
maxwofford Jan 7, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 37 additions & 13 deletions lib/flavor.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@ export const sample = (arr, seed = '') => {
return arr[Math.floor(random * arr.length)]
}

export const bound = (num, min, max) => {
return Math.min(Math.max(num, min), max)
}

export const loadingSpinners = ['compass.svg', 'skull.svg']
const loadingMsg = ['']

const pseudoRandom = (seed) => {
return Math.sin(seed * 10000) / 2 + 0.5
Expand All @@ -17,6 +20,12 @@ export const zeroMessage = [
"Can't buy nothin' with nothin'!",
]

// export const shopBlessed = [
// "Blimey! You got a blessing, didja? Well that's gotta do good for business seeing such upstanding pirate folk shoping here.",
// "Wow! You got the boon of a pirate's blessing!",
// `Blimey, a pirate's blessing! *She ${transcript('superstitions')}, according to pirate tradition.* Please, shop to your heart's content!`,
// ]

export const purchaseWords = [
// Don't uniquify this! Some are rarer than others
'Acquire',
Expand All @@ -32,6 +41,7 @@ export const purchaseWords = [
'Plunder',
'Plunder',
'BitTorrent',
'Loot',
]

export const cantAffordWords = [
Expand All @@ -45,16 +55,30 @@ export const cantAffordWords = [
// "when you're richer...",
]

export const shopBanner = [
'buy something or get out!',
'spend your doubloons here!',
'get that booty!',
'NO REFUNDS',
'feeling overburdened by money?',
'plundered from the best dead adventurers in the land',
'we accept doubloons and PiratePay™',
'YARR',
'🏴‍☠️',
"you wouldn't download a ship...",
"These prices are walkin' the plank!",
export const shopIcons = {
freaking: 'https://cloud-iz667ljca-hack-club-bot.vercel.app/0freaking.png',
ded: 'https://cloud-iz667ljca-hack-club-bot.vercel.app/1ded.png',
info: 'https://cloud-iz667ljca-hack-club-bot.vercel.app/2info.png',
peefest: 'https://cloud-iz667ljca-hack-club-bot.vercel.app/3pf.png',
threat: 'https://cloud-iz667ljca-hack-club-bot.vercel.app/4threatened.png',
reading: 'https://cloud-iz667ljca-hack-club-bot.vercel.app/5reading_2.png',
reading2: 'https://cloud-iz667ljca-hack-club-bot.vercel.app/6reading.png',
scallywag: 'https://cloud-iz667ljca-hack-club-bot.vercel.app/7scallywag.png',
search: 'https://cloud-iz667ljca-hack-club-bot.vercel.app/8searching_2.png',
search2: 'https://cloud-iz667ljca-hack-club-bot.vercel.app/9searching.png',
question: 'https://cloud-nfmmdwony-hack-club-bot.vercel.app/0000.png',
cute: 'https://cloud-nfmmdwony-hack-club-bot.vercel.app/3003.png',
tinfoil: 'https://cloud-nfmmdwony-hack-club-bot.vercel.app/4004.png',
holdingEars: 'https://cloud-nfmmdwony-hack-club-bot.vercel.app/4004.png', // todo: draw this
woah: 'https://cloud-e9zuzn0u0-hack-club-bot.vercel.app/3003.png',
thumbs: 'https://cloud-r04a8za6c-hack-club-bot.vercel.app/1001.png',
fluster:
'https://cloud-3wb98dblo-hack-club-bot.vercel.app/0untitled_artwork.gif',
bapanada:
'https://cloud-o4qa8261z-hack-club-bot.vercel.app/0270a4575-6fa8-4946-b5c8-3fb5b8d9b722-1660621656235.webp',
}

export const outOfStock = [
"icon:question|where'd all the stock go?",
'icon:question|come back when more washes up on shore',
]
48 changes: 48 additions & 0 deletions lib/transcript.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import transcriptData from './transcript.yml'

function transcript(path, context = {}, skipArrays = true, depth = 0) {
console.log({ path, depth })
if (depth > 10) {
console.log('hit recursion depth 10!')
return
}
try {
const leaf = getDescendantProp(transcriptData, path, skipArrays)
if (typeof leaf === 'string') {
return evalInContext('`' + leaf + '`', { ...context, t: transcript })
}
if (leaf === undefined) {
return `transcript.${path}`
} else {
return leaf
}
} catch (e) {
console.error(e)
return path
}
}

export { transcript }

function evalInContext(js, context) {
if (process.env.NODE_ENV === 'development') {
console.log({ js, context })
}
return function () {
return eval(js)
}.call(context)
}

function getDescendantProp(obj, desc, skipArrays) {
const arr = desc.split('.')
if (process.env.NODE_ENV === 'development') {
console.log({ arr, obj })
}
while (arr.length) {
obj = obj[arr.shift()]
if (Array.isArray(obj) && skipArrays) {
obj = obj[Math.floor(Math.random() * obj.length)]
}
}
return obj
}
224 changes: 224 additions & 0 deletions lib/transcript.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,224 @@
legalThings:
- ®
- ™
- ℠
- ℗
- ©
- ${this.t('legalThings')}${this.t('legalThings')}
banner:
- buy something or get out!
- spend your doubloons here!
- get that booty!
- NO REFUNDS
- feeling overburdened by money?
- plundered from the best dead adventurers in the land
- we accept doubloons and PiratePay${this.t('legalThings')}
- YARR
- 🏴‍☠️
- you wouldn't download a ship...
- These prices are walkin' the plank!
- you break it, you buy it!
- pirate-owned and operated!
- caveat emptor
- all sales are final
selfClick:
- icon:question|w-what? but I'm not for sale
- icon:info|The only thing for sale here is the merchandise
- icon:holdingEars|hey buddy, hands to yourself
- icon:holdingEars|hands off ${this.t('pirateyThings')}!
- icon:threat|I'll have you know I'm not for sale!
- icon:threat|You ain't gonna plunder this booty!
- icon:freaking|N-no! You can't buy me! |icon:sticker|I'm not gonna be some collectible sticker sheet!
- icon:threat|hey!! i'm allergic to cursors!
- icon:thumbs|guess who's got 2 thumbs and is not for sale!
- click me one more time, i dare you... ya ${this.t('pirateyThings')}!
- icon:freaking|w-wait. |icon:blushing|you want to buy me? really?
- icon:fluster|stop clicking! t-that tickles!
- icon:fluster|w-wait. you want to buy me? really?
- d-did you just click me?!
- icon:threat|*angry raccoon chittering noises*
superstitionItems:
- black cat
- rabbit's foot
- horseshoe
- horse's paw
- rabbit's shoe
- monkey's paw
- whole rabbit
- broken mirror
- ladder
- whole salt shaker
- four-leaf clover
- three-leaf clover with an extra leaf taped on
- whole leprechaun (not just the bones)
- whole leprechaun (not just the charms)
- whole leprechaun (not just the gold)
- lucky coin
- pinch of salt
superstitions:
- spits over shoulder
- spins around three times
- knocks on wood
- throws salt over shoulder
- crosses fingers
- signs the cross with her tail
- spits in her hat
- grabs a rabbit's foot
- pins a ${this.t('superstitionItems')} to her hat
- ties up a ${this.t('superstitionItems')} above the door frame
- throws a ${this.t('superstitionItems')} over her shoulder # be careful. this one... is pretty out there
blessed:
- Blimey! You got a blessing, didja? Well that's gotta do good for business seeing such upstanding pirate folk shoping here.
- Wow! You got the boon of a pirate's blessing!
- Blow me down! You got a pirate's blessing! That's gotta be good luck for me shop!
- Blimey, a pirate's blessing! *She ${this.t('superstitions')}, according to pirate tradition.* Please, shop to your heart's content!
cursed:
- Blimey! You've been cursed? *${this.t('superstitions')}* and then *${this.t('superstitions')}*
- Ye've been cursed? *${this.t('superstitions')}* and then *${this.t('superstitions')}*
- By the seven seas! You've been cursed? *spits over shoulder*
- You've been cursed?! Get off me island you ${this.t('pirateyThings')}!
- Hang on, you're cursed? Go take a long walk off a short plank!
- Hold on... are you cursed? Read the sign– no blessing, no business!
- wait... are you C-C-CURSED?! I don't want any trouble!
getout:
- Getouttahere!
- out out out!
- Get out!
- Come back once you got gold!
- whaddya take me for? wonathose nonprofit thingymajigs?
- you tryin ta steal from a thief! what's the world coming to!
- you can't take this stuff, i stole it fare and square!
- you trying to pull my tail?!
help:
- how can i help ye?
- wadya wanna buy?
- the mutinied capt' trash-beard at your service!
greetings:
- icon:bapanada|speed:2|*sigh* . . . bapanada |speed:default|icon:freaking|errrr... i mean... |icon:scallywag|come in!
- well, if it isnt my favorite customer!
- Ahh, my favorite customer!
- raccoon has wares if you have coin!
- have a pretty penny you want to spend?
- your pockets look shiny today!
- that coinpurse looks heavy, let me help you with that.
- I have a feeling you're going to like what you see today.
- Hey there! You look like you could use some help.
- Oh, hello! How can I help you have a GARBAGE day?
tooManyBells:
- icon:freaking|Alright! |icon:threat|Enough with the |speed:4.1|BLOODY BELLS!~
- icon:holdingears|S-stop it! I got sensitive hear-holes over here!
- icon:freaking|stop ringing that annoysing bell!
- icon:notamused|argh, I'm regretting plundering that bell in the first place
- icon:threat|I swear on me mum & all my ${21 + Math.floor(Math.random() * 8)} siblings, stop with the bell!
- icon:threat|I didn't get |speed:4|MAROONED|speed:default| on this dog-forsaken island to listen to that!
- S-stop taunting me with those infernal bells!
- Go annoy some tanuki on another island with those bells!
pirateyThings:
- bilge rat
- salty dog
- scurvy dog
- scallywag
- landlubber
- scurvy swashbuckler
- scurvy pirate
- scurvy sea dog
- scurvy sea rat
- scurvy sea scoundrel
- scurvy rat
- scurvy scallywag
music:
- icon:question|where's that music coming from?
- icon:question|who's playing that music?
- icon:question|where are those instruments?
- icon:holdingEars|that music is a little loud
doot: # someone clicks a trumpet while music is playing
- icon:freaking|stop with the trumpet!
fav:
removed:
- icon:question|ah, not interested in the [${this.name.toUpperCase()}]?
- icon:info|awwww, not interested in the [${this.name.toUpperCase()}]?
- icon:thinking|hmmmm... is the [${this.name.toUpperCase()}] not to your liking?
- icon:freaking|you're not interested in the [${this.name.toUpperCase()}]?|icon:threat| you try finding stuff to sell while being marooned on an island!
- icon:question|you don't want the [${this.name.toUpperCase()}]? |icon:info|just try finding it anywhere else for ${this.price} doubloons!
added:
- icon:question|ah, interested in the [${this.name.toUpperCase()}]?
- icon:info|for ${this.price} doubloons, some would consider this a steal!|icon:holdingEars|. . . please don't report me to the authorities...
- icon:info|for ${this.price} doubloons, some would consider this a steal!
- icon:info|ooooh, that's a good choice!
- icon:info|you've got good taste!
- icon:info|just try finding [${this.name.toUpperCase()}] anywhere else for ${this.price} doubloons!
addedCanAffort:
- "|icon:thinking| . . . |icon:question| hold on... can't you already affort that?"
- '|icon:thinking| . . . |icon:question| but... you can already affort that?'
- "|icon:thinking| . . . |icon:question| why'd you fave that if you can already buy it?"
- '|icon:thinking| . . . |icon:question| you know you already have enough to buy that, right?'
floatingThings:
- skull
- coconut
- empty bottle
- ship in a bottle
- drift wood
- turtle shell
- sea shell
- seaweed
- washed up beach ball # wilson!!!
- washed up boot
bigNumbers:
- '[ArithmeticOverflowException]'
- '[LargeIntegerOverflow]'
- a barrel-full
- a nautical butt-load
item:
base: icon:question|you want to buy a |speed:2.5|[${this.name.toUpperCase()}]|speed:default|?
generic:
- \|icon:question|see something you like?
- \|icon:info|those have been pretty popular lately. . . |icon:peefest|speed:4.5| *internally crying as she thinks about the ${this.t('floatingThings')} and ${this.t('floatingThings')} that have been her only customers for the past 3 years*|speed:default
- \|icon:question|uuuuh, how many you want?
- \|icon:cute|yes yes, you buy now!
- '|icon:cute|youuuuu... pay this much? [${this.price} doubloons]'
- '|icon:info|why does this label say DO NOT EAT?'
item_pinecil_20:
- ${this.t('item.generic')}
- '|icon:info|*Warning: May contain lead'
- \|icon:info|I hafta be careful with these– me first mate has a lead allergy!
- \|icon:info|Be careful if you have a lead allergy!
- \|icon:freaking|hot! |speed:3.5|Hot! |speed:4|HOT!|speed:default
- \|icon:info|yes, let me fetch one from the back...|icon:freaking|speed:3.5|ow!|speed:4| Ow!|speed:4.5| OWOWOWOWOWOW!
- \|icon:cute|It’s like welding but tiny!
item_github_notebook_37:
- "|icon:info| if only i could read... |icon:holdingEars| *sigh* |icon:info| i'd be able to tell you all about it"
- "|icon:info|I can't read, but I can tell you it's a notebook!"
- '|icon:cute|a place to draw your treasure maps!'
- '|icon:info|write down where you buried your treasure!'
- '|icon:info|write down where you buried your treasure!|icon:holdingEars| *sigh* . . . i wish i could read'
item_factorio:
- "|icon:fluster| you have NO IDEA how much time i've sunk into this game"
- "|icon:info| interesting fact: this is a GREAT way to kill the time when you're marooned on a deserted island"
item_bambu_lab_a1_mini_49:
- If a picture is worth 1000 words, a 3d print should be worth ${this.t('bigNumbers')}
- Oh, do they print in chocolate?!
- It's like a hot glue gun, but with more steps
item_100mhz_oscilloscope_53:
- if i were a smarter racoon i'd say something about "waves"
item_hot_glue_gun:
- cheaper than a 3d printer!
item_pile_of_stickers_10:
- it's like graffiti, but with less commitment
- the perfect way to vandalize your own property
- ooooh, are you going to put that on your laptop?
- Puts the "ad" in "adhesive"!
item_signed_photo_of_malted_19:
- '|icon:info|Due to inflation the average photo is only worth 700 words'
- "|icon:info|I'm not sure who this is, but they look important!"
- '|icon:question|i dont know why i have these, they just washed up one day'
item_digital_calipers_50:
- '|icon:scallywag|measure twice, stab once!'
- used to make sure your plank is just the right walkin' length
- as sharp as a cutlass!
- as sharp as me first mate's hook!
item_flipper_32:
- \|icon:info|I've tried these, but watch out. . .|icon:wet| they aren't water proof
- \|icon:tinfoil|*dons her tinfoil captain's hat*|speed:0.3|. . .|speed:default| don't point that at me head
item_hack_club_socks__34:
- they aren't hacker socks, but any ${this.t('pirateyThings')} worth their salt can make do...
- as a raccoon, i've already got natural socks, but these are good for me crew!
28 changes: 28 additions & 0 deletions lib/useEventEmitter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { useRef, useEffect } from 'react'

const globalEmitter = new EventTarget()

export function useEventEmitter() {
const emitterRef = useRef(globalEmitter)

const emit = (eventName: string, detail?: any) => {
emitterRef.current.dispatchEvent(new CustomEvent(eventName, { detail }))
}

// handy helper for shopkeeper interactions
const emitYap = (interaction: string) => {
emitterRef.current.dispatchEvent(
new CustomEvent('shopkeeper', { detail: { interaction } }),
)
}

const on = (eventName: string, callback: (event: CustomEvent) => void) => {
emitterRef.current.addEventListener(eventName, callback as EventListener)
}

const off = (eventName: string, callback: (event: CustomEvent) => void) => {
emitterRef.current.removeEventListener(eventName, callback as EventListener)
}

return { emit, on, off, emitYap }
}
Loading
Loading