const { SlashCommandBuilder, EmbedBuilder } = require('discord.js'); const { getServerMode, getEmbedColor, EMBED_COLORS } = require('../utils/modeHelper'); const { updateStandaloneXp } = require('../utils/standaloneXp'); const SYMBOLS = ['🍒', '🍋', '🍊', '🍇', '⭐', '💎', '7️⃣']; const WEIGHTS = [30, 25, 20, 15, 7, 2, 1]; const PAYOUTS = { '🍒🍒🍒': 5, '🍋🍋🍋': 10, '🍊🍊🍊': 15, '🍇🍇🍇': 20, '⭐⭐⭐': 50, '💎💎💎': 100, '7️⃣7️⃣7️⃣': 250, }; const slotsCooldowns = new Map(); const COOLDOWN = 30000; function spin() { const totalWeight = WEIGHTS.reduce((a, b) => a + b, 0); const random = Math.random() * totalWeight; let cumulativeWeight = 0; for (let i = 0; i < SYMBOLS.length; i++) { cumulativeWeight += WEIGHTS[i]; if (random < cumulativeWeight) { return SYMBOLS[i]; } } return SYMBOLS[0]; } module.exports = { data: new SlashCommandBuilder() .setName('slots') .setDescription('Try your luck at the slot machine!') .addIntegerOption(option => option.setName('bet') .setDescription('XP to bet (10-50)') .setRequired(false) .setMinValue(10) .setMaxValue(50) ), async execute(interaction, supabase, client) { const bet = interaction.options.getInteger('bet') || 10; const userId = interaction.user.id; const guildId = interaction.guildId; const mode = await getServerMode(supabase, interaction.guildId); const cooldownKey = `${guildId}-${userId}`; const lastSpin = slotsCooldowns.get(cooldownKey); if (lastSpin && Date.now() - lastSpin < COOLDOWN) { const remaining = Math.ceil((COOLDOWN - (Date.now() - lastSpin)) / 1000); return interaction.reply({ content: `You can spin again in ${remaining} seconds.`, ephemeral: true }); } slotsCooldowns.set(cooldownKey, Date.now()); const slot1 = spin(); const slot2 = spin(); const slot3 = spin(); const result = `${slot1}${slot2}${slot3}`; const payout = PAYOUTS[result]; let netGain = 0; let resultMessage = ''; let color = getEmbedColor(mode); if (payout) { netGain = bet * payout; resultMessage = `🎉 JACKPOT! You won **${netGain} XP**!`; color = EMBED_COLORS.success; } else if (slot1 === slot2 || slot2 === slot3 || slot1 === slot3) { netGain = Math.floor(bet * 0.5); resultMessage = `Nice! Two matching! You won **${netGain} XP**!`; color = 0xF59E0B; } else { netGain = -bet; resultMessage = `No luck this time. You lost **${bet} XP**.`; color = EMBED_COLORS.error; } if (netGain !== 0) { if (mode === 'standalone') { await updateStandaloneXp(supabase, userId, guildId, netGain, interaction.user.username); } else if (supabase) { try { const { data: profile } = await supabase .from('user_profiles') .select('xp') .eq('discord_id', userId) .maybeSingle(); if (profile) { const newXp = Math.max(0, (profile.xp || 0) + netGain); await supabase .from('user_profiles') .update({ xp: newXp }) .eq('discord_id', userId); } } catch (e) {} } } const embed = new EmbedBuilder() .setColor(color) .setTitle('🎰 Slot Machine') .setDescription(` ╔═══════════╗ ║ ${slot1} ${slot2} ${slot3} ║ ╚═══════════╝ ${resultMessage} `) .addFields({ name: '💰 Bet', value: `${bet} XP`, inline: true }) .setFooter({ text: `${interaction.user.username}` }) .setTimestamp(); await interaction.reply({ embeds: [embed] }); }, };