diff --git a/README.md b/README.md index a779feb..9900624 100644 --- a/README.md +++ b/README.md @@ -43,10 +43,25 @@ When using/giving an item or qbucks the itemlock will be set at the start of the Admins can toggle the itemlock on chatters with the [`itemlock`](#administrative-commands) command. This will stop a chatter from giving, receiving and using items and qweribucks. It will NOT stop them from using items by cheering, but if that cheer item usage fails, they will not be given an equivalent item as compensation. -Items can be used with the alias as a command (example: `blast qwerinope`) or with the [`use` command](#item-commands). +Items can be used with the alias as a command (example: `blast qwerinope`) or with the [`use` command](#qweribucksitem-commands). When an Item is used it is removed from the inventory of the chatter. +### Lootbox + +There is no lootbox item, you just get loot when using the [`getloot` command](#qweribucksitem-commands). The cooldown is 10 minutes. You can't get loot if your itemlock is set. +Each loot drop has between 50 and 150 qbucks. Here is the drop table for items with chances. + +ITEM|RATE +-|- +`grenade`|`1/5` +`blaster`|`1/5` +`tnt`|`1/20` +`silver bullet`|`1/250` + +Each of these rates get pulled 5 times, then the result is added to your inventory. +It's theoretically possible to get 5 of each item. + ### Chatterbot/streamerbot This depends on if the `CHATTER_IS_STREAMER` environment variable is set. @@ -70,22 +85,18 @@ COMMAND|FUNCTION|USER|ALIASES|DISABLEABLE `stats [target]`|Get timeout and some item stats for yourself or specified user this month|anyone|`stats` `monthlystats`|:white_check_mark: `alltime [target]`|Get timeout and some item stats for yourself or specified user of all time|anyone|`alltime` `alltimestats`|:white_check_mark: -### Qweribucks commands +### Qweribucks/Item commands COMMAND|FUNCTION|USER|ALIASES|DISABLEABLE -|-|-|-|- +`getloot`|Get a random assortment of items and qbucks every 10 minutes. [(drop rates)](#lootbox)|anyone|`getloot` `loot` `dig`|:white_check_mark: `getbalance [target]`|Get balance of target or self|anyone|`getbalance` `balance` `qbucks` `qweribucks` `wallet` `getwallet`|:white_check_mark: `donate {target} {amount}`|Give the targeted user some or all of your qweribucks|anyone|`donate`|:white_check_mark: -`admindonate {target} {amount}`|Gives the targeted user amount of qweribucks|admins|`admindonate`|:white_check_mark: - -### Item commands - -COMMAND|FUNCTION|USER|ALIASES|DISABLEABLE --|-|-|-|- `iteminfo {item}`|Get item function and aliases|anyone|`iteminfo` `itemhelp` `info`|:white_check_mark: `inventory [target]`|Get inventory contents of target or self|anyone|`inventory` `inv`|:white_check_mark: `give {target} {item} {amount}`|Give targeted user amount of items|anyone|`give`|:white_check_mark: `use {item} ...`|Use item. More info at [The items section](#items)|anyone|`use`|:x: +`admindonate {target} {amount}`|Gives the targeted user amount of qweribucks|admins|`admindonate`|:white_check_mark: `admingive {target} {item} {amount}`|Give targeted user amount of new items|admins|`admingive`|:white_check_mark: ### Administrative commands diff --git a/src/commands/getloot.ts b/src/commands/getloot.ts new file mode 100644 index 0000000..a6c169a --- /dev/null +++ b/src/commands/getloot.ts @@ -0,0 +1,60 @@ +import { redis } from "bun"; +import { Command, sendMessage } from "commands"; +import { getUserRecord, updateUserRecord } from "db/dbUser"; +import items from "items"; +import { buildTimeString } from "lib/dateManager"; + +const COOLDOWN = 10 * 60 * 1000; // 10 mins (ms) + +export default new Command('getloot', ['getloot', 'dig', 'loot'], 'chatter', async (msg, user) => { + if (!await redis.exists('streamIsLive')) { await sendMessage(`No loot while stream is offline`, msg.messageId); return; }; + if (await user.itemLock()) { await sendMessage(`Cannot get loot (itemlock)`, msg.messageId); return; }; + const userData = await getUserRecord(user); + const lastlootbox = Date.parse(userData.lastlootbox); + const now = Date.now(); + if ((lastlootbox + COOLDOWN) > now) { await sendMessage(`Wait ${buildTimeString(now - COOLDOWN, lastlootbox)} for another lootbox.`, msg.messageId); return; }; + + await user.setLock(); + + userData.lastlootbox = new Date(now).toISOString(); + + const gainedqbucks = Math.floor(Math.random() * 100) + 50; // range from 50 to 150 + userData.balance += gainedqbucks; + + const itemDiff = { + grenade: 0, + blaster: 0, + tnt: 0, + silverbullet: 0 + }; + + for (let i = 0; i < 5; i++) { + if (Math.floor(Math.random() * 5) === 0) itemDiff.grenade += 1; + if (Math.floor(Math.random() * 5) === 0) itemDiff.blaster += 1; + if (Math.floor(Math.random() * 25) === 0) itemDiff.tnt += 1; + if (Math.floor(Math.random() * 250) === 0) itemDiff.silverbullet += 1; + }; + + for (const [item, amount] of Object.entries(itemDiff)) { + if (userData.inventory[item]) userData.inventory[item] += amount; + }; + + const itemstrings: string[] = [`${gainedqbucks} qbucks`]; + + for (const [item, amount] of Object.entries(itemDiff)) { + if (amount === 0) continue; + const selection = items.get(item); + if (!selection) continue; + itemstrings.push(`${amount} ${selection.prettyName + (amount === 1 ? '' : selection.plural)}`); + }; + + const last = itemstrings.pop(); + const itemstring = itemstrings.length === 0 ? last : itemstrings.join(', ') + " and " + last; + const message = `You got ${itemstring}`; + + await Promise.all([ + updateUserRecord(user, userData), + sendMessage(message, msg.messageId), + user.clearLock() + ]); +}); diff --git a/src/events/streamState.ts b/src/events/streamState.ts new file mode 100644 index 0000000..ee3fc4f --- /dev/null +++ b/src/events/streamState.ts @@ -0,0 +1,10 @@ +import { redis } from "bun"; +import { eventSub, streamerId } from "main"; + +eventSub.onStreamOnline(streamerId, async _msg => { + await redis.set('streamIsLive', '1'); +}); + +eventSub.onStreamOffline(streamerId, async _msg => { + await redis.del('streamIsLive'); +}); diff --git a/src/index.ts b/src/index.ts index 47eda27..95bb29c 100644 --- a/src/index.ts +++ b/src/index.ts @@ -45,6 +45,9 @@ mods.forEach(async mod => { logger.info(`Set the mod status of ${mod.userDisplayName} in the Redis/Valkey database.`); }); +const streamdata = await streamerApi.streams.getStreamByUserId(streamerId); +if (streamdata) await redis.set('streamIsLive', '1'); + await import("./events"); await import("./web");