diff --git a/src/server/routes/api.js b/src/server/routes/api.js index afb0fad..207a255 100644 --- a/src/server/routes/api.js +++ b/src/server/routes/api.js @@ -131,6 +131,9 @@ export function apiRoutes(client, io) { case "ultra": caseTypeVal = 1500; break; + case "esport": + caseTypeVal = 50; + break; default: return res.status(400).json({ error: "Invalid case type." }); } @@ -214,6 +217,53 @@ export function apiRoutes(client, io) { } }); + router.post("/skin/:uuid/instant-sell", (req, res) => { + const { userId } = req.body; + try { + const skin = getSkin.get(req.params.uuid); + const skinData = skins.find((s) => s.uuid === skin.uuid); + if ( + !skinData + ) { + return res.status(403).json({ error: "Invalid skin." }); + } + if (skin.user_id !== userId) { + return res.status(403).json({ error: "User does not own this skin." }); + } + + const commandUser = getUser.get(userId); + if (!commandUser) { + return res.status(404).json({ error: "User not found." }); + } + const sellPrice = Math.floor(skin.currentPrice * 0.75); + + insertLog.run({ + id: `${userId}-${Date.now()}`, + user_id: userId, + action: "VALO_SKIN_INSTANT_SELL", + target_user_id: null, + coins_amount: sellPrice, + user_new_amount: commandUser.coins + sellPrice, + }); + updateUserCoins.run({ + id: userId, + coins: commandUser.coins + sellPrice, + }); + updateSkin.run({ + uuid: skin.uuid, + user_id: null, + currentLvl: null, + currentChroma: null, + currentPrice: null, + }); + console.log(`${commandUser.username} instantly sold skin ${skin.uuid} for ${sellPrice} FlopoCoins`); + res.status(200).json({ sellPrice }); + } catch (error) { + console.error("Error fetching skin upgrade:", error); + res.status(500).json({ error: "Failed to fetch skin upgrade." }); + } + }); + router.get("/skin-upgrade/:uuid/fetch", (req, res) => { try { const skin = getSkin.get(req.params.uuid); @@ -247,7 +297,7 @@ export function apiRoutes(client, io) { if (skin.user_id !== userId) { return res.status(403).json({ error: "User does not own this skin." }); } - const upgradePrice = Math.floor(parseFloat(skin.maxPrice) / 10); + const { successProb, destructionProb, upgradePrice } = getSkinUpgradeProbs(skin, skinData); const commandUser = getUser.get(userId); if (!commandUser) { @@ -272,7 +322,7 @@ export function apiRoutes(client, io) { let succeeded = false; let destructed = false; - const { successProb, destructionProb } = getSkinUpgradeProbs(skin, skinData); + const roll = Math.random(); if (roll < destructionProb) { destructed = true; diff --git a/src/utils/caseOpening.js b/src/utils/caseOpening.js index 4ddf9c9..eb10790 100644 --- a/src/utils/caseOpening.js +++ b/src/utils/caseOpening.js @@ -2,6 +2,24 @@ import { getAllAvailableSkins, getSkin } from "../database/index.js"; import { skins } from "../game/state.js"; export async function drawCaseContent(caseType = "standard") { + if (caseType === "esport") { + // Esport case: return all esport skins + try { + const dbSkins = getAllAvailableSkins.all(); + const esportSkins = skins + .filter((s) => dbSkins.find((dbSkin) => dbSkin.displayName.includes("Classic (VCT") && dbSkin.uuid === s.uuid)) + .map((s) => { + const dbSkin = getSkin.get(s.uuid); + return { + ...s, // Shallow copy to avoid mutating the imported 'skins' object + tierColor: dbSkin?.tierColor, + }; + }); + return esportSkins; + } catch (e) { + console.log(e); + } + } let tierWeights; switch (caseType) { case "standard": @@ -91,8 +109,13 @@ export async function drawCaseContent(caseType = "standard") { } export function drawCaseSkin(caseContent) { - const randomSelectedSkinIndex = Math.floor(Math.random() * (caseContent.length - 1)); - const randomSelectedSkinUuid = caseContent[randomSelectedSkinIndex].uuid; + try { + const randomSelectedSkinIndex = Math.floor(Math.random() * (caseContent.length - 1)); + const randomSelectedSkinUuid = caseContent[randomSelectedSkinIndex].uuid; + } catch (e) { + console.log(e); + throw new Error("Failed to draw a skin from the case content."); + } const dbSkin = getSkin.get(randomSelectedSkinUuid); const randomSkinData = skins.find((skin) => skin.uuid === dbSkin.uuid); @@ -130,9 +153,18 @@ export function drawCaseSkin(caseContent) { export function getSkinUpgradeProbs(skin, skinData) { const successProb = - (1 - (((skin.currentChroma + skin.currentLvl + skinData.chromas.length + skinData.levels.length) / 18) * (parseInt(skin.tierRank) / 4)))/2; + (1 - (((skin.currentChroma + skin.currentLvl + skinData.chromas.length + skinData.levels.length) / 18) * (parseInt(skin.tierRank) / 4)))/1.5; const destructionProb = ((skin.currentChroma + skinData.levels.length) / (skinData.chromas.length + skinData.levels.length)) * (parseInt(skin.tierRank) / 5) * 0.075; - const upgradePrice = Math.max(Math.floor(parseFloat(skin.currentPrice) * (1 - successProb)), 1); + const nextLvl = skin.currentLvl < skinData.levels.length ? skin.currentLvl + 1 : skin.currentLvl; + const nextChroma = skin.currentLvl === skinData.levels.length && skin.currentChroma < skinData.chromas.length ? skin.currentChroma + 1 : skin.currentChroma; + const calculateNextPrice = () => { + let result = parseFloat(skin.basePrice); + result *= 1 + nextLvl / Math.max(skinData.levels.length, 2); + result *= 1 + nextChroma / 4; + return parseFloat(result.toFixed(0)); + }; + const diff = calculateNextPrice() - parseFloat(skin.currentPrice); + const upgradePrice = Math.max(Math.floor(diff * successProb), 1); return { successProb, destructionProb, upgradePrice }; }