Hvacker/src/games/hvacoins/prestige.js

302 lines
8.9 KiB
JavaScript

const { commas, quackGradeMultiplier, prestigeMultiplier, makeBackup, userHasCheckedQuackgrade, getUser } = require('./utils')
const { quackStore } = require('./quackstore')
const buyableItems = require('./buyableItems')
const slack = require('../../slack')
const possiblePrestige = coins => {
let p = 0
while (totalCostForPrestige(p + 1) <= coins) {
p += 1
}
return p
}
const tpcRecMemo = []
const totalCostForPrestige = prestigeLevel => {
if (prestigeLevel === 0) {
return 0
}
return (tpcRecMemo[prestigeLevel]) || (tpcRecMemo[prestigeLevel] = 1_000_000_000_000 * Math.pow(prestigeLevel, 3) + totalCostForPrestige(prestigeLevel - 1))
}
const prestigeRoute = async ({ say, args, user }) => {
const possible = possiblePrestige(user.coinsAllTime)
const current = user.prestige ??= 0
if (args[0] === 'me') {
await say(
'This will permanently remove all of your items, upgrades, and coins!\n\n' +
'Say \'!!prestige me\' to confirm.'
)
} else {
const currentCost = totalCostForPrestige(possible)
const nextCost = totalCostForPrestige(possible + 1)
const diff = nextCost - currentCost
const progress = user.coinsAllTime - currentCost
const bars = Math.round((progress / diff) * 10)
const empty = 10 - bars
const progressBar = '[' + '='.repeat(bars) + ' '.repeat(empty) + ']'
await say(
`Current Prestige: ${commas(current)}\n\n` +
`Quacks gained if you prestige now: ${commas(possible - current)}\n\n` +
`Next quack progress: \`${progressBar} ${commas(diff)} \`\n\n` +
'Say \'!prestige me\' to start the prestige process.' +
`\n\nYour prestige is currently boosting your CPS by ${commas((prestigeMultiplier(user) - 1) * 100)}%`
)
}
}//, true, adminOnly)
const prestigeConfirmRoute = async ({ event, say, user, YEET }) => {
if (YEET) {
return say(prestigeMenu(user))
}
const possible = possiblePrestige(user.coinsAllTime)
const current = user.prestige
if (possible <= current) {
await say('You don\'t have enough HVAC to prestige right now!')
return
}
if (event?.text !== '!!prestige me') {
await say('Say exactly \'!!prestige me\' to confirm')
return
}
await makeBackup()
user.isPrestiging = true
user.quacks ??= 0
user.quacks += (possible - user.prestige)
user.prestige = possible
user.highestEver = 0
user.coins = 0
user.items = {}
user.holdings = {}
const starterUpgrades = (user.quackUpgrades?.starter || [])
starterUpgrades.forEach(upgradeName => quackStore[upgradeName].effect(user))
user.upgrades = {}
await say(prestigeMenu(user))
await say(`Say !quack _upgrade-name_ to purchase new quackgrades!`)
//await say('You prestiged! Check out !quackstore to see what you can buy!')
}
const quackStoreListing = (showCost = true) => ([name, upgrade]) =>
`:${upgrade.emoji}: *${name}* - ${showCost ? 'Costs' : 'Worth'} *${upgrade.cost} Quack.*\n\n_${upgrade.description}_`
const allUserQuackUpgrades = user =>
Object.entries(user.quackUpgrades || {})
.map(([type, upgrades]) => upgrades).flatMap(x => x)
const hasPreReqs = user => ([name, upgrade]) => {
if (!upgrade.preReqs) {
return true
}
const allUserUpgrades = allUserQuackUpgrades(user)
return upgrade.preReqs.every(preReq => allUserUpgrades.includes(preReq))
}
const owns = (user, [name, upgrade]) => allUserQuackUpgrades(user).includes(name)
const ownedQuackItems = user => Object.entries(quackStore).filter(upgrade => owns(user, upgrade))
const unownedQuackItems = user => Object.entries(quackStore).filter(upgrade => !owns(user, upgrade))
const quackStoreText = user =>
unownedQuackItems(user)
.filter(hasPreReqs(user))
.map(quackStoreListing(true))
.join('\n\n') +
`\n\nYou have ${user.quacks ??= 0} quacks to spend.` +
`\nQuackStore upgrades are currently boosting your CPS by ${commas((quackGradeMultiplier(user) - 1) * 100)}%`
const quackStoreRoute = async ({ user, say, args, YEET }) => {
user.quackUpgrades ??= {}
if (!args[0] || !YEET) {
await say(quackStoreText(user))
return
}
const quackItem = quackStore[args[0]]
if (!quackItem || !unownedQuackItems(user).find(([name]) => name === args[0])) {
await say(`'${args[0]}' is not available in the quack store!`)
return
}
const quacks = user.quacks ??= 0
if (quackItem.cost > quacks) {
await say(`${args[0]} costs ${quackItem.cost} Quacks, but you only have ${quacks}!`)
return
}
user.quacks -= quackItem.cost
user.quackUpgrades[quackItem.type] ??= []
user.quackUpgrades[quackItem.type].push(args[0])
if (quackItem.type === 'starter') {
quackItem.effect(user)
}
await say(`You bought ${args[0]}!`)
}
const buyQuackGradeButton = quackgrade => {
//console.log('buyQuackGradeButton', quackgrade[1])
const [name, object] = quackgrade
return {
type: 'section',
text: {
type: 'mrkdwn',
text: `:${object.emoji}: ${object.name} - ${object.cost} Quacks\n_${object.description}_`
},
accessory: {
type: 'button',
text: {
type: 'plain_text',
text: 'Buy',
emoji: true
},
value: 'click_me_123',
action_id: `buy-quackgrade-${name}`
}
}
}
const prestigeMenu = (user, extraMessage = '') => {
user.quackUpgrades ??= {}
const quacks = user.quacks ??= 0
return {
text: 'Prestige menu',
blocks: [
{
type: 'section',
text: {
type: 'mrkdwn',
text: `${extraMessage && extraMessage + '\n'}\n_You have ${quacks} quacks to spend._`
// text: `${extraMessage && extraMessage + '\n'}_*PRESTIGE IN PROGRESS*_\n_You have ${quacks} quacks to spend. You may ONLY spend quacks on this menu._`
}
},
// {
// type: 'section',
// text: {
// type: 'mrkdwn',
// text: '~Challenge mode~ _TODO_'
// },
// accessory: {
// type: 'static_select',
// placeholder: {
// type: 'plain_text',
// text: 'No challenge',
// emoji: true
// },
// options: [
// {
// text: {
// type: 'plain_text',
// text: 'No challenge',
// emoji: true
// },
// value: 'no-challenge'
// },
// /*
// {
// text: {
// type: 'plain_text',
// text: 'Clean Start (no prestige bonuses)',
// emoji: true
// },
// value: 'clean-start'
// }*/
// ],
// action_id: 'challenge_select-action'
// }
// },
{
type: 'section',
text: {
type: 'mrkdwn',
text: '*Available Quackgrades:*'
}
},
...unownedQuackItems(user).filter(hasPreReqs(user)).map(buyQuackGradeButton),
// {
// type: 'actions',
// elements: [
// {
// type: 'button',
// text: {
// type: 'plain_text',
// text: 'Complete Prestige',
// emoji: true
// },
// value: 'complete_prestige',
// action_id: 'complete_prestige'
// }
// ]
// }
]
}
}
const buyQuackGrade = async ({ body, ack, say, trueSay, payload }) => {
await ack()
const buying = payload.action_id.substring('buy-quackgrade-'.length)
console.log(`buyQuackGrade ${buying} clicked`)
const user = getUser(body.user.id)
// if (!user.isPrestiging) {
// console.log('You must be prestiging!')
// return say(`You must be prestiging to use this menu!`)
// }
const words = ['', buying, body.actions[0].text]
const [, ...args] = words
let extraMessage = ''
//say = async text => extraMessage = text
console.log('quackStoreRoute')
await quackStoreRoute({ say, args, user, YEET: true })
await slack.app.client.chat.update({
channel: body.channel.id,
ts: body.message.ts,
...prestigeMenu(user, extraMessage)
})
}
Object.keys(quackStore).forEach(itemName => slack.app.action('buy-quackgrade-' + itemName, buyQuackGrade))
slack.app.action('complete_prestige', async ({ body, ack, say }) => {
await ack()
const user = getUser(body.user.id)
delete user.isPrestiging
await slack.app.client.chat.delete({
channel: body.channel.id,
ts: body.message.ts,
})
await say(`Prestige complete!`)
})
const prestigeMenuRoute = async ({ say, user }) => {
user.quackUpgrades ??= {}
user.quacks ??= 0
await say(prestigeMenu(user))
}
const ownedQuacksText = user =>
ownedQuackItems(user)
.filter(hasPreReqs(user))
.map(quackStoreListing(false))
.join('\n\n') +
`\n\nQuackStore upgrades are currently boosting your CPS by ${commas((quackGradeMultiplier(user) - 1) * 100)}%`
const ownedQuacksRoute = async ({ say, user }) => {
user.quackUpgrades ??= {}
user.quacks ??= 0
await say(ownedQuacksText(user))
}
module.exports = {
quackStoreRoute,
prestigeRoute,
prestigeConfirmRoute,
prestigeMenuRoute,
ownedQuacksRoute
}