diff --git a/src/games/hvacoins/achievements.js b/src/games/hvacoins/achievements.js index 4e31118..94c220c 100644 --- a/src/games/hvacoins/achievements.js +++ b/src/games/hvacoins/achievements.js @@ -23,6 +23,21 @@ module.exports = { name: 'Lucky Gem Acquired', description: 'It sparkles', emoji: 'gem' + }, + bugFinder: { + name: 'Bug-Finder', + description: 'You must have a magnifying glass or something', + emoji: 'bug' + }, + bigBets: { + name: 'Make a bet over 100B', + description: 'I like big bets, and that\'s the truth', + emoji: 'slot_machine' + }, + ignited: { + name: 'You light my fire, baby', + description: 'And you pay attention to descriptions!', + emoji: 'fire' } } diff --git a/src/games/hvacoins/index.js b/src/games/hvacoins/index.js index 45c37d2..9dd17ad 100644 --- a/src/games/hvacoins/index.js +++ b/src/games/hvacoins/index.js @@ -5,6 +5,20 @@ const buyableItems = require('./buyableItems') const upgrades = require('./upgrades') const achievements = require('./achievements') +// const readline = require('readline').createInterface({ +// input: process.stdin, +// output: process.stdout +// }) +// const read = () => { +// readline.question(`What do YOU want? `, async want => { +// want && await slack.messageSage(want) +// read() +// }) +// } +// ;(async () => { +// read() +// })(); + const saveFile = 'hvacoins.json' const parseOr = (parseable, orFunc) => { @@ -58,9 +72,17 @@ const helpText = (highestCoins, user) => Object.entries(buyableItems) const getUpgradeEmoji = upgrade => upgrade.emoji || buyableItems[upgrade.type].emoji const upgradeText = user => { - return (!user ? '' : '\n\n' + Object.entries(upgrades).filter(([upgradeName, upgrade]) => !hasUpgrade(user, upgrade, upgradeName)).filter(([, upgrade]) => upgrade.condition(user)).map(([key, value]) => `:${getUpgradeEmoji(value)}: *${key}* - ${commas(value.cost)}\n_${value.description}_`).join('\n\n')) + - '\n\n:grey_question::grey_question::grey_question:' + - '\n\nJust type \'!upgrade upgrade_name\' to purchase' + const userDoesNotHave = ([upgradeName, upgrade]) => !hasUpgrade(user, upgrade, upgradeName) + const userMeetsCondition = ([, upgrade]) => upgrade.condition(user) + const format = ([key, value]) => `:${getUpgradeEmoji(value)}: *${key}* - ${commas(value.cost)}\n_${value.description}_` + return '\n\n' + + Object.entries(upgrades) + .filter(userDoesNotHave) + .filter(userMeetsCondition) + .map(format) + .join('\n\n') + + '\n\n:grey_question::grey_question::grey_question:' + + '\n\nJust type \'!upgrade upgrade_name\' to purchase' } const getUser = userId => { @@ -90,13 +112,15 @@ const setHighestCoins = userId => { const hasUpgrade = (user, upgrade, upgradeName) => user.upgrades[upgrade.type]?.includes(upgradeName) -const addAchievement = async (user, achievementName, say) => { +const addAchievement = (user, achievementName, say) => { if (user.achievements[achievementName]) { return } - user.achievements[achievementName] = true - saveGame() - await say(`You earned the achievement ${achievements[achievementName].name}!`) + setTimeout(async () => { + user.achievements[achievementName] = true + saveGame() + await say(`You earned the achievement ${achievements[achievementName].name}!`) + }, 500) } const alwaysAccessible = () => true @@ -130,7 +154,7 @@ slack.onMessage(async ({ event, say }) => { return } if (!c?.condition(event.user)) { - await say(`Command '${words[0]}' not found`) + //await say(`Command '${words[0]}' not found`) return } if (words[1] === 'help') { @@ -144,6 +168,10 @@ command( ['!a', '!ach', '!achievements'], 'List your glorious achievements', async ({ event, say }) => { + if (event.channel_type !== 'im') { + await say('Please only use !ach in DMs!') + return + } const user = getUser(event.user) const achievementCount = Object.keys(user.achievements).length @@ -214,17 +242,17 @@ command( if (random > 0.9967) { diff = 500 + Math.floor(c * 0.10) + secondsOfCps(60 * 30) prefix = `:gem: You found a lucky gem worth ${commas(diff)} HVAC!\n` - await addAchievement(user, 'luckyGem', say) + addAchievement(user, 'luckyGem', say) await slack.messageSage(`${slack.ourUsers[event.user]} FOUND A LUCKY GEM COIN WORTH ${commas(diff)} HVAC!`) } else if (random > 0.986) { diff = 50 + Math.floor(c * 0.025) + secondsOfCps(60) prefix = `:goldbrick: You found a lucky gold coin worth ${commas(diff)} HVAC!\n` await slack.messageSage(`${slack.ourUsers[event.user]} found a lucky gold coin worth ${commas(diff)} HVAC!`) - await addAchievement(user, 'goldBrick', say) + addAchievement(user, 'goldBrick', say) } else if (random > 0.96) { diff = 10 + Math.floor(c * 0.01) + secondsOfCps(10) prefix = `:money_with_wings: You found a lucky green coin worth ${commas(diff)} HVAC!\n` - await addAchievement(user, 'greenCoin', say) + addAchievement(user, 'greenCoin', say) } else { prefix = `You mined one HVAC.\n` diff = 1 @@ -261,6 +289,9 @@ command( await say(`You don\'t have that many coins! You have ${commas(user.coins)}.`) return } + if (n > 100_000_000_000) { + addAchievement(user, 'bigBets', say) + } user.coins -= n let outcome if (Math.random() > 0.5) { @@ -317,8 +348,12 @@ command( ['!upgrade', '!u'], 'Improve the performance of your HVAC-generators.\n' + ' Say \'!upgrade\' to list available upgrades, or \'!upgrade upgrade_name\' to purchase.', - async ({ userId, say, words }) => { - const user = getUser(userId) + async ({ event, say, words }) => { + if (event.channel_type !== 'im') { + await say('Please only use !upgrade in DMs!') + return + } + const user = getUser(event.user) const upgradeName = words[1] if (!upgradeName) { await say(upgradeText(user)) @@ -340,7 +375,7 @@ command( await say('That item does not exist!') return } - const c = getCoins(userId) + const c = getCoins(event.user) if (c < upgrade.cost) { await say(`You don't have enough coins! You have ${commas(c)}, but you need ${commas(upgrade.cost)}`) return @@ -369,7 +404,7 @@ command( if (!buying) { const highestCoins = user.highestEver || user.coins || 1 if (buyableItems.quade.baseCost < highestCoins * 100) { - await addAchievement(user, 'seeTheQuade', say) + addAchievement(user, 'seeTheQuade', say) } await say(helpText(highestCoins, user)) return @@ -402,15 +437,16 @@ command( command( ['!check', '!ch'], 'Check how many coins another player has', - async ({ target, say }) => { + async ({ say, words }) => { + const target = words[1] if (!target?.startsWith('<@') || !target.endsWith('>')) { await say('Target must be a valid @') return } const targetId = target.substring(2, target.length - 1) if (targetId !== 'U0344TFA7HQ') { - const user = getUser(targetId) - await say(`<@${targetId}> has ${commas(user.coins)} HVAC.`) + const coins = getCoins(targetId) + await say(`<@${targetId}> has ${commas(coins)} HVAC.`) } else { const members = (await slack.app.client.conversations.members({channel: slack.temperatureChannelId})).members const humanMembers = members.filter(name => name.length === 11) @@ -534,4 +570,57 @@ command( `They currently have ${commas(getCoins(targetId))} HVAC Coins\n\n` + `${collection(targetId)}\n\n` ) + }, true, adminOnly) + +command( + ['!steal', '!sagesteal'], + 'Highly illegal', + async ({ event, words, say }) => { + const userId = event.user + const user = getUser(userId) + let [, target] = words + const amount = getCoins(userId) / 100 + if (!amount || amount < 0) { + return + } + let targetId + if (!target?.startsWith('<@') || !target.endsWith('>')) { + targetId = slack.sageUserId + } else { + targetId = target.substring(2, target.length - 1) + } + if (user.coins < amount) { + return + } + const targetUser = getUser(targetId) + user.coins -= amount + targetUser.coins += amount + await say(`Stealing is wrong. Gave ${commas(Math.floor(amount))} of your HVAC to ${slack.ourUsers[targetId]}`) + }, true) + +command( + ['!lottery'], + 'Once per day, try for a big win!', + async ({ event, say }) => { + const user = getUser(event.user) + addAchievement(user, 'ignited', say) + }, true) + +command( + ['!ignite'], + 'You found me!', + async ({ event, say }) => { + const user = getUser(event.user) + addAchievement(user, 'ignited', say) + } +) +command( + ['!giveach'], + '!giveach @player ach_name', + async ({ words, say }) => { + const targetId = words[1].substring(2, words[1].length - 1) + const user = getUser(targetId) + console.log(user, words[2], say) + addAchievement(user, words[2], say) + saveGame() }, true, adminOnly) \ No newline at end of file diff --git a/src/games/hvacoins/upgrades.js b/src/games/hvacoins/upgrades.js index 69bdad9..09a92f5 100644 --- a/src/games/hvacoins/upgrades.js +++ b/src/games/hvacoins/upgrades.js @@ -6,6 +6,8 @@ const basic = ({ type, description, count, cost }) => ({ effect: itemCps => itemCps * 2 }) +const nothing = itemCps => itemCps + module.exports = { doubleClick: basic({ type: 'mouse', @@ -13,96 +15,152 @@ module.exports = { count: 1, cost: 1_000, }), + stinkierCheese: basic({ + type: 'mouse', + description: 'Mice are doubly motivated to hunt down HVAC Coins', + count: 10, + cost: 21_000, + }), biggerTeeth: basic({ type: 'mouse', description: 'Mice can intimidate twice as much HVAC out of their victims.', count: 25, cost: 50_000, }), + fasterComputers: basic({ type: 'accountant', description: 'Accountants can ~steal~ optimize twice as much HVAC!', count: 1, cost: 11_000, }), + lackOfMorality: basic({ + type: 'accountant', + description: 'Accountants are taking a hint from nearby CEOs.', + count: 10, + cost: 200_000, + }), widerBrains: basic({ type: 'accountant', description: 'For accountant do double of thinking.', count: 25, cost: 550_000, }), + biggerBlowhole: basic({ type: 'whale', description: 'With all that extra air, whales have double power!', count: 1, cost: 120_000, }), + sassyWhales: basic({ + type: 'whale', + description: 'These are the kind of whales that know how to get twice as much done', + count: 10, + cost: 3_000_000, + }), thinnerWater: basic({ type: 'whale', description: 'Whales can move twice as quickly through this physics-defying liquid', count: 25, cost: 6_000_000, }), + greasyTracks: basic({ type: 'train', description: 'Lets trains deliver HVAC twice as efficiently', count: 1, cost: 1_300_000, }), + rocketThrusters: basic({ + type: 'train', + description: 'That\'ll put some quack on your track', + count: 10, + cost: 22_000_000, + }), loudConductors: basic({ type: 'train', description: 'Conductors can onboard twice as much HVAC', count: 25, cost: 65_000_000, }), + gasolineFire: basic({ type: 'fire', description: 'Extremely good for breathing in.', count: 1, cost: 14_000_000, }), + extremelyDryFuel: basic({ + type: 'fire', + description: 'Use the ignite command for a secret achievement.', + count: 10, + cost: 163_000_000, + }), cavemanFire: basic({ type: 'fire', description: 'They just don\'t make \'em like they used to.', count: 25, cost: 700_000_000, }), + spoonerang: basic({ type: 'boomerang', description: 'Scoops up HVAC mid-flight', count: 1, cost: 200_000_000, }), + boomerAng: basic({ + type: 'boomerang', + description: 'It\'s... old.', + count: 10, + cost: 1_200_000_000, + }), doubleRang: basic({ type: 'boomerang', description: 'You throw one, but somehow catch two', count: 25, cost: 10_000_000_000, }), + lunarPower: basic({ type: 'moon', description: 'Out with the sol, in with the lun!', count: 1, cost: 3_300_000_000, }), + womanOnTheMoon: basic({ + type: 'moon', + description: 'There\'s no reason for it not to be a woman!', + count: 10, + cost: 39_700_000_000, + }), doubleCraters: basic({ type: 'moon', description: 'Making every side look like the dark side.', count: 25, cost: 165_000_000_000, }), + glassButterfly: basic({ type: 'butterfly', description: 'Not your grandma\'s universe manipulation.', count: 1, cost: 51_000_000_000, }), + monarchMigration: basic({ + type: 'butterfly', + description: 'This upgrade brought to you by milkweed.', + count: 10, + cost: 870_000_000_000, + }), quadWing: basic({ type: 'butterfly', description: 'Sounds a lot like a trillion bees buzzing inside your head.', count: 25, cost: 2_550_000_000_000, }), + silverMirror: basic({ type: 'mirror', description: 'Excellent for stabbing vampires.', @@ -136,5 +194,14 @@ module.exports = { cost: 10_000_000_000, effect: (itemCps, user) => Math.ceil(itemCps * 1.1) }, + + // moreUpgrades: { + // type: 'general', + // description: 'Adds additional upgrades', + // condition: user => Object.entries(user.items).reduce((total, [, countOwned]) => countOwned + total, 0) >= 400, + // emoji: 'cookie', + // cost: 10_000_000_000_000, + // effect: nothing + // }, } diff --git a/src/slack/index.js b/src/slack/index.js index 129663f..1693af7 100644 --- a/src/slack/index.js +++ b/src/slack/index.js @@ -69,11 +69,10 @@ const ourUsers = { let activePolls = {} app.event('message', async ({ event, context, client, say }) => { - console.log(event) for (const listener of messageListeners) { listener({ event, say }) } - const words = event.text?.split('\s') + console.log('MSG', ourUsers[event.user], "'" + event.text + "'", new Date().toLocaleTimeString()) if (event.user === 'U028BMEBWBV' && event.channel === 'D0347Q4H9FE') { if (event.text?.startsWith('!say ') || event.text?.startsWith('!say\n')) { await postToTechThermostatChannel(event.text.substring(4).trim())