jillo-bot/src/lib/rpg/craftingStations.ts

127 lines
3.9 KiB
TypeScript

import { pickRandom } from '../util';
import { DefaultItems, Item, Items, formatItem, formatItems, formatItemsArray, getDefaultItem, getItemQuantity } from './items';
export interface CraftingStation {
key: string,
name: string,
verb?: string,
description: string,
emoji: string,
requires?: Item,
// in seconds
cooldown?: number,
formatRecipe?: (inputs: Items[], requirements: Items[], outputs: Items[], disableBold?: boolean) => string,
manipulateResults?: (outputs: Items[]) => Items[]
}
export function getStation(key: string) {
return craftingStations.find(station => station.key === key);
}
export const defaultVerb = 'Crafted';
const rollBunch = (outputs: Items[]) => {
const totalItems = outputs.reduce((a, b) => a + b.quantity, 0);
// grab from 1/3 to the entire pool, ensure it never goes below 1
const rolledItems = Math.max(Math.round(totalItems/3 + Math.random() * totalItems*2/3), 1);
const res: Items[] = [];
for (let i = 0; i < rolledItems; i++) {
const rolled = pickRandom(outputs);
const r = res.find(r => r.item.id === rolled.item.id);
if (r) {
if (r.quantity === rolled.quantity) {
// don't roll more than can be rolled
i--;
} else {
r.quantity = r.quantity + 1;
}
} else {
res.push({ item: rolled.item, quantity: 1 });
}
}
return res;
};
const formatMaybeCountable = (inputs: Items[], requirements: Items[], outputs: Items[], disableBold = false) =>
`${formatItemsArray(inputs, disableBold)} ${requirements.length > 0 ? `w/ ${formatItemsArray(requirements, disableBold)}: ` : ''}${outputs.map(i => formatItems(i.item, i.quantity, disableBold) + '?').join(' ')}`;
const formatMaybe = (inputs: Items[], requirements: Items[], outputs: Items[], disableBold = false) =>
`${formatItemsArray(inputs, disableBold)} ${requirements.length > 0 ? `w/ ${formatItemsArray(requirements, disableBold)} ` : ''}=> ${outputs.map(i => formatItem(i.item, disableBold) + '?').join(' ')}`;
export const craftingStations: CraftingStation[] = [
{
key: 'forage',
name: 'Forage',
verb: 'Foraged',
description: 'Pick up various sticks and stones from the forest',
emoji: '🌲',
cooldown: 60 * 5,
formatRecipe: formatMaybeCountable,
manipulateResults: rollBunch
},
{
key: 'hand',
name: 'Hand',
verb: 'Made',
description: 'You can use your hands to make a small assortment of things',
emoji: '✋'
},
{
key: 'workbench',
name: 'Workbench',
description: 'A place for you to work with tools, for simple things',
emoji: '🛠️',
requires: getDefaultItem(DefaultItems.WORKBENCH)
},
{
key: 'fishing',
name: 'Fishing',
verb: 'Fished up',
description: 'fish gaming wednesday',
emoji: '🎣',
cooldown: 60 * 60 * 2,
requires: getDefaultItem(DefaultItems.FISHING_ROD),
formatRecipe: formatMaybe,
// weighted random
manipulateResults: (outputs) => {
const pool: Item[] = [];
for (const out of outputs) {
for (let i = 0; i < out.quantity; i++) {
pool.push(out.item);
}
}
return [{ item: pickRandom(pool), quantity: 1 }];
}
},
{
key: 'mining',
name: 'Mining',
verb: 'Mined',
description: 'mine diamonds',
emoji: '⛏️',
cooldown: 60 * 30,
requires: getDefaultItem(DefaultItems.MINESHAFT),
formatRecipe: formatMaybeCountable,
manipulateResults: rollBunch,
},
{
key: 'smelting',
name: 'Smelting',
verb: 'Smelt',
description: 'Smelt ores, minerals, food, whatever you please',
emoji: '🔥',
cooldown: 30,
requires: getDefaultItem(DefaultItems.FURNACE),
},
];
export async function canUseStation(user: string, station: CraftingStation) {
if (!station.requires) return true;
const inv = await getItemQuantity(user, station.requires.id);
return inv.quantity > 0;
}
export function verb(station: CraftingStation) {
return station.verb || defaultVerb;
}