Merge pull request #62 from cassoule/milo-251226

fixes
This commit is contained in:
Milo Gourvest
2025-12-27 04:54:55 +01:00
committed by GitHub
2 changed files with 88 additions and 6 deletions

View File

@@ -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;

View File

@@ -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 };
}