X-Git-Url: https://git.xangelo.ca/?p=sketchy-heroes.git;a=blobdiff_plain;f=src%2Froutes%2Finventory%2Fpick.ts;fp=src%2Froutes%2Finventory%2Fpick.ts;h=b7c29be8923f94d0fd40b79701180b50eca0ea65;hp=0000000000000000000000000000000000000000;hb=b5d3cc37fddebff8dcdf1ef0cdd3a626811f14d3;hpb=20dc560a75cfd6ddc8a66956315a30001779ec24 diff --git a/src/routes/inventory/pick.ts b/src/routes/inventory/pick.ts new file mode 100644 index 0000000..b7c29be --- /dev/null +++ b/src/routes/inventory/pick.ts @@ -0,0 +1,155 @@ +import { server } from '@lib/server'; +import { Static, Type } from '@sinclair/typebox'; +import { prisma } from '@lib/db'; +import { ForbiddenError, NotFoundError } from '@lib/http-errors'; +import { logger } from '@lib/logger'; +import {weighted} from '@lib/weighted'; +import {Inventory, Rarity} from '@prisma/client'; +import Decimal from 'decimal.js'; +import { random, sample } from 'lodash'; + +type rarityDropRates = { + rarity: Rarity, + weight: number +}; + +type StatModifierStat = { + name: string; + min: number; + max: number; +} +type StatModifiers = { + stats: StatModifierStat[], + required: string[] +}; + +const WorldDropInput = Type.Object({ + params: Type.Object({ + playerId: Type.String(), + dropId: Type.String() + }) +}); + +type InputType = Static; + +export type pickWorldDropOutput = { + item: Inventory +} + +export const pickWorldDrop = server.post('/v1/accounts/:playerId/pick/:dropId', { + schema: WorldDropInput, + authenicated: true +}, async req => { + const player = await prisma.player.findUnique({ + where: { + id: req.params.playerId + } + }); + + if(!player) { + throw new ForbiddenError(); + } + const drop = await prisma.worldDrop.findUnique({ + where: { + id: req.params.dropId + }, + include: { + baseItem: true + } + }); + + if(!drop) { + throw new NotFoundError(`Drop ${req.params.dropId} is not valid`); + } + + // figure out the item stats and award to the player + // 1. get rarity - this functions as a modifier for everything else + let selectedRarity = weighted(drop.baseItem.rarityDropRates as rarityDropRates[], i => i.weight); + + if(selectedRarity === undefined) { + selectedRarity = { + rarity: Rarity.COMMON, + weight: 1 + }; + } + + console.log(selectedRarity); + + // 2. figure out durability + //We're just going to bump durability by ~25% for each rarity type + const rarityDurabilityMap = { + [Rarity.COMMON]: 1, + [Rarity.UNCOMMON]: 1.15, + [Rarity.RARE]: 1.26 + } + const durability = Math.ceil(drop.baseItem.durability * rarityDurabilityMap[selectedRarity.rarity]); + + console.log('durability', durability, drop.baseItem, rarityDurabilityMap, selectedRarity.rarity); + + // 3. figure out stat modifiers + const stats: Record = { + pow: 0, + zest: 0, + woosh: 0, + luck: 0, + aha: 0, + wow: 0, + stamina: 0, + hp: 0 + }; + let selectedStats = 0; + const mods = drop.baseItem.statModifiers as StatModifiers; + mods.required.forEach(name => { + mods.stats.filter(s => s.name === name).forEach(stat => { + stats[stat.name] += random(stat.min, stat.max); + selectedStats++; + }); + }); + + // the item now has the "Common" number of stat modifiers. + // uncommon will have 1 extra stat modifier + // rare will have 2 extra stat modifiers + if(selectedRarity.rarity === Rarity.UNCOMMON) { + const stat = sample(mods.stats); + if(stat) { + selectedStats++; + stats[stat.name] += random(stat.min, stat.max); + } + } + + if(selectedRarity.rarity === Rarity.RARE) { + for(let i = 0; i < 2; ++i) { + const stat = sample(mods.stats); + if(stat) { + selectedStats++; + stats[stat.name] += random(stat.min, stat.max); + } + } + } + + // 4. Calculate uses until discovery + // each stat assigned to an item increases its uses + // by 20. + // Each rarity level adds another 20 + const rarityDiscovery = [Rarity.COMMON, Rarity.UNCOMMON, Rarity.RARE]; + const discover = selectedStats * 20 + (rarityDiscovery.indexOf(selectedRarity.rarity) > 0 ? rarityDiscovery.indexOf(selectedRarity.rarity) * 20 : 0); + + + // 5. Give the player the new item, but set it to undiscovered + const inventoryItem = await prisma.inventory.create({ + data: { + playerId: player.id, + itemId: drop.itemId, + discovered: false, + usesUntilDiscovery: discover, + maxDurability: durability, + currentDurability: durability, + rarity: selectedRarity.rarity, + type: drop.baseItem.type, + statModifiers: stats, + stackable: false + } + }); + + return {item: inventoryItem}; +});