Roulette

  • community
  • minigames
  • by limon
  • Takaro v0.0.21
  • all
View export JSON

A casino-style roulette game where players can bet currency on different outcomes.

Configuration 3

Settings you fill in when installing the module on a server.

SettingTypeDefaultDescription
minimumBet minimumBet number 10 The minimum amount a player can bet on a single spin.
maximumBet maximumBet number 100 The maximum amount a player can bet on a single spin.
houseEdge houseEdge number 5 Percentage of winnings the house takes as profit (5 = 5%).
Raw config schema
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "required": [],
  "additionalProperties": false,
  "properties": {
    "minimumBet": {
      "title": "minimumBet",
      "description": "The minimum amount a player can bet on a single spin.",
      "default": 10,
      "type": "number"
    },
    "maximumBet": {
      "title": "maximumBet",
      "description": "The maximum amount a player can bet on a single spin.",
      "default": 100,
      "type": "number"
    },
    "houseEdge": {
      "title": "houseEdge",
      "description": "Percentage of winnings the house takes as profit (5 = 5%).",
      "default": 5,
      "type": "number"
    }
  }
}
Raw UI schema
{}

Commands 4

Chat commands players trigger in game.

  • roulettestats

    Shows your roulette statistics

    Command source
    import { takaro, data } from '@takaro/helpers';
    
    async function main() {
        const { player, gameServerId, module: mod } = data;
    
        const statsKey = 'roulette_stats';
        const statsSearch = await takaro.variable.variableControllerSearch({
            filters: {
                key: [statsKey],
                playerId: [player.id],
                gameServerId: [gameServerId],
                moduleId: [mod.moduleId],
            },
        });
    
        if (statsSearch.data.data.length === 0) {
            await player.pm("🎰 You haven't played any roulette games yet!");
            return;
        }
    
        const stats = JSON.parse(statsSearch.data.data[0].value);
        const winRate = stats.played > 0 ? ((stats.won / stats.played) * 100).toFixed(2) : 0;
    
        const statsDisplay = [
            '🎰 🎲 YOUR ROULETTE STATISTICS 🎲 🎰',
            '',
            `Games played: ${stats.played}`,
            `Games won: ${stats.won}`,
            `Games lost: ${stats.lost}`,
            `Win rate: ${winRate}%`,
            `Total wagered: ${stats.totalWagered} currency`,
            '',
            'Good luck on your next spin! 🍀'
        ];
    
        await player.pm(statsDisplay.join('\n'));
    }
    
    await main();
  • roulettereset

    Reset a player's roulette statistics (admin only).

    ArgumentTypeDefaultHelp
    player string Player whose stats to reset
    Command source
    import { takaro, data, checkPermission, TakaroUserError } from '@takaro/helpers';
    
    async function main() {
        const { player, gameServerId, arguments: args, module: mod, pog } = data;
    
        // Check admin permission
        if (!checkPermission(pog, 'ROULETTE_ADMIN')) {
            throw new TakaroUserError('You do not have permission to reset roulette statistics!');
        }
    
        // Get target player
        if (!args.player) {
            throw new TakaroUserError('Please specify a player whose stats you want to reset.');
        }
    
        const targetPlayerId = args.player.playerId;
        const targetPlayerName = args.player.name;
    
        // Find stats to reset
        const statsKey = 'roulette_stats';
        const statsSearch = await takaro.variable.variableControllerSearch({
            filters: {
                key: [statsKey],
                playerId: [targetPlayerId],
                gameServerId: [gameServerId],
                moduleId: [mod.moduleId],
            },
        });
    
        if (statsSearch.data.data.length === 0) {
            throw new TakaroUserError(`No roulette statistics found for ${targetPlayerName}.`);
        }
    
        // Delete the stats variable
        await takaro.variable.variableControllerDelete(statsSearch.data.data[0].id);
    
        // Also delete any cooldown variables
        const cooldownKey = 'roulette_cooldown';
        const cooldownSearch = await takaro.variable.variableControllerSearch({
            filters: {
                key: [cooldownKey],
                playerId: [targetPlayerId],
                gameServerId: [gameServerId],
                moduleId: [mod.moduleId],
            },
        });
    
        if (cooldownSearch.data.data.length > 0) {
            await takaro.variable.variableControllerDelete(cooldownSearch.data.data[0].id);
        }
    
        await player.pm(`✅ Successfully reset roulette statistics for ${targetPlayerName}.`);
    
        // Log the action
        await takaro.gameserver.gameServerControllerExecuteCommand(gameServerId, {
            command: `say [Admin] ${player.name} has reset ${targetPlayerName}'s roulette statistics.`,
        });
    }
    
    await main();
  • roulette

    Place a bet and spin the roulette wheel.

    ArgumentTypeDefaultHelp
    betType string Type of bet (red, black, even, odd, high, low) or a number 0-36
    amount number Amount to bet
    Command source
    import { takaro, data, checkPermission, TakaroUserError } from '@takaro/helpers';
    
    async function main() {
        const { player, gameServerId, arguments: args, module: mod, pog } = data;
    
        // Check permission
        if (!checkPermission(pog, 'ROULETTE_PLAY')) {
            throw new TakaroUserError('You do not have permission to play roulette!');
        }
    
        // Get the input from the first argument (bet type + possible number)
        const betInput = args.betType ? args.betType.toLowerCase() : null;
        const betAmount = Number(args.amount);
    
        if (!betInput) {
            throw new TakaroUserError('Please specify what you want to bet on!');
        }
    
        // Validate bet amount
        if (isNaN(betAmount) || betAmount <= 0) {
            throw new TakaroUserError('Please enter a valid positive bet amount!');
        }
    
        // Parse the bet type and number from the input
        let betType = null;
        let betNumber = null;
    
        // Define valid bet types
        const simpleBetTypes = ['red', 'black', 'even', 'odd', 'high', 'low'];
    
        // Check if it's a simple bet type (red, black, etc.)
        if (simpleBetTypes.includes(betInput)) {
            betType = betInput;
        }
        // Check if it's a number bet (e.g., "number17" or just "17")
        else if (betInput.startsWith('number')) {
            betType = 'number';
            betNumber = Number(betInput.substring(6)); // Extract number after "number"
        }
        // Check if it's just a number
        else if (!isNaN(Number(betInput)) && Number(betInput) >= 0 && Number(betInput) <= 36) {
            betType = 'number';
            betNumber = Number(betInput);
        }
        // Unknown bet type
        else {
            throw new TakaroUserError(`Invalid bet type! Valid options: ${simpleBetTypes.join(', ')}, or a number 0-36\nExamples: /roulette red 100 or /roulette 17 50`);
        }
    
        // Validate number if it's a number bet
        if (betType === 'number' && (isNaN(betNumber) || betNumber < 0 || betNumber > 36 || !Number.isInteger(betNumber))) {
            throw new TakaroUserError('Please specify a valid number between 0 and 36!');
        }
    
        // Get minimum and maximum bet limits
        const minimumBet = mod.userConfig.minimumBet;
        let maximumBet = mod.userConfig.maximumBet;
    
        // Check higher limits permission
        const higherLimitsPermission = checkPermission(pog, 'ROULETTE_HIGHER_LIMITS');
        if (higherLimitsPermission && higherLimitsPermission.count > 0) {
            maximumBet *= higherLimitsPermission.count;
        }
    
        // Validate bet amount against limits
        if (betAmount < minimumBet) {
            throw new TakaroUserError(`The minimum bet is ${minimumBet} currency!`);
        }
        if (betAmount > maximumBet) {
            throw new TakaroUserError(`The maximum bet is ${maximumBet} currency!`);
        }
    
        // Check if player is on cooldown
        const cooldownTime = mod.userConfig.cooldownTime;
        if (cooldownTime > 0) {  // Only check cooldown if it's enabled
            const cooldownKey = 'roulette_cooldown';
            const cooldownVar = await takaro.variable.variableControllerSearch({
                filters: {
                    key: [cooldownKey],
                    playerId: [player.id],
                    gameServerId: [gameServerId],
                    moduleId: [mod.moduleId],
                },
            });
    
            if (cooldownVar.data.data.length > 0) {
                const lastSpinTime = new Date(cooldownVar.data.data[0].value).getTime();
                const currentTime = Date.now();
                const timeElapsed = currentTime - lastSpinTime;
    
                if (timeElapsed < cooldownTime) {
                    const timeRemaining = Math.ceil((cooldownTime - timeElapsed) / 1000);
                    throw new TakaroUserError(`Please wait ${timeRemaining} seconds before spinning again!`);
                }
    
                // Update cooldown
                await takaro.variable.variableControllerUpdate(cooldownVar.data.data[0].id, {
                    value: new Date().toISOString(),
                });
            } else {
                // Create cooldown
                await takaro.variable.variableControllerCreate({
                    key: cooldownKey,
                    value: new Date().toISOString(),
                    gameServerId,
                    moduleId: mod.moduleId,
                    playerId: player.id,
                });
            }
        }
    
        // Check if player has enough currency
        const playerData = await takaro.playerOnGameserver.playerOnGameServerControllerGetOne(gameServerId, player.id);
        const currentBalance = playerData.data.data.currency;
    
        if (currentBalance < betAmount) {
            throw new TakaroUserError(`You need ${betAmount} currency to place this bet. You only have ${currentBalance}.`);
        }
    
        // Deduct the bet amount
        await takaro.playerOnGameserver.playerOnGameServerControllerDeductCurrency(
            gameServerId,
            player.id,
            {
                currency: betAmount
            }
        );
    
        await player.pm(`🎰 You've placed a ${betAmount} currency bet on ${betType}${betType === 'number' ? ' ' + betNumber : ''}...`);
    
        // Define the roulette wheel
        const redNumbers = [1, 3, 5, 7, 9, 12, 14, 16, 18, 19, 21, 23, 25, 27, 30, 32, 34, 36];
        const blackNumbers = [2, 4, 6, 8, 10, 11, 13, 15, 17, 20, 22, 24, 26, 28, 29, 31, 33, 35];
    
        // Spin the wheel (generate a random number between 0 and 36)
        const result = Math.floor(Math.random() * 37);
        const isRed = redNumbers.includes(result);
        const isBlack = blackNumbers.includes(result);
        const isEven = result !== 0 && result % 2 === 0;
        const isOdd = result % 2 === 1;
        const isHigh = result >= 19 && result <= 36;
        const isLow = result >= 1 && result <= 18;
    
        // Display the result with Unicode for visual effect
        let resultColor = isRed ? '🔴' : isBlack ? '⚫' : '🟢';
        await player.pm(`${resultColor} The ball lands on ${result}! ${resultColor}`);
    
        // Determine if player won
        let playerWon = false;
        let payoutMultiplier = 0;
        const houseEdge = mod.userConfig.houseEdge / 100;  // Convert percentage to decimal
    
        switch (betType) {
            case 'red':
                payoutMultiplier = 2 * (1 - houseEdge);
                playerWon = isRed;
                break;
            case 'black':
                payoutMultiplier = 2 * (1 - houseEdge);
                playerWon = isBlack;
                break;
            case 'even':
                payoutMultiplier = 2 * (1 - houseEdge);
                playerWon = isEven;
                break;
            case 'odd':
                payoutMultiplier = 2 * (1 - houseEdge);
                playerWon = isOdd;
                break;
            case 'high':
                payoutMultiplier = 2 * (1 - houseEdge);
                playerWon = isHigh;
                break;
            case 'low':
                payoutMultiplier = 2 * (1 - houseEdge);
                playerWon = isLow;
                break;
            case 'number':
                payoutMultiplier = 36 * (1 - houseEdge);
                playerWon = (result === betNumber);
                break;
        }
    
        // Update player stats
        await updatePlayerStats(player.id, gameServerId, mod.moduleId, betAmount, playerWon);
    
        // Pay out winnings if player won
        if (playerWon) {
            const winnings = Math.floor(betAmount * payoutMultiplier);
            await takaro.playerOnGameserver.playerOnGameServerControllerAddCurrency(
                gameServerId,
                player.id,
                {
                    currency: winnings
                }
            );
            await player.pm(`🎉 Congratulations! You've won ${winnings} currency! 🎉`);
    
            // Broadcast big wins to everyone
            if (winnings >= 1000) {
                await takaro.gameserver.gameServerControllerSendMessage(gameServerId, {
                    message: `🎰 ${player.name} just won ${winnings} currency at the roulette table! 🎰`
                });
            }
        } else {
            await player.pm('❌ Better luck next time! ❌');
        }
    
        // Get updated balance
        const updatedPlayerData = await takaro.playerOnGameserver.playerOnGameServerControllerGetOne(gameServerId, player.id);
        await player.pm(`Current balance: ${updatedPlayerData.data.data.currency} currency`);
    }
    
    async function updatePlayerStats(playerId, gameServerId, moduleId, betAmount, won) {
        const statsKey = 'roulette_stats';
        const statsSearch = await takaro.variable.variableControllerSearch({
            filters: {
                key: [statsKey],
                playerId: [playerId],
                gameServerId: [gameServerId],
                moduleId: [moduleId],
            },
        });
    
        let stats = {
            played: 0,
            won: 0,
            lost: 0,
            totalWagered: 0,
        };
    
        if (statsSearch.data.data.length > 0) {
            stats = JSON.parse(statsSearch.data.data[0].value);
            await takaro.variable.variableControllerUpdate(statsSearch.data.data[0].id, {
                value: JSON.stringify({
                    played: stats.played + 1,
                    won: stats.won + (won ? 1 : 0),
                    lost: stats.lost + (won ? 0 : 1),
                    totalWagered: stats.totalWagered + betAmount,
                }),
            });
        } else {
            await takaro.variable.variableControllerCreate({
                key: statsKey,
                value: JSON.stringify({
                    played: 1,
                    won: won ? 1 : 0,
                    lost: won ? 0 : 1,
                    totalWagered: betAmount,
                }),
                gameServerId,
                moduleId: moduleId,
                playerId: playerId,
            });
        }
    }
    
    await main();
  • rouletterules

    Shows the rules and payouts for roulette.

    Command source
    import { takaro, data } from '@takaro/helpers';
    
    async function main() {
        const { player, module: mod } = data;
    
        const minimumBet = mod.userConfig.minimumBet;
        const maximumBet = mod.userConfig.maximumBet;
        const houseEdge = mod.userConfig.houseEdge;
    
        // Part 1: Introduction and basic info
        const rules1 = [
            `🎰 🎲 ROULETTE RULES 🎲 🎰`,
            '',
            `Minimum bet: ${minimumBet} currency`,
            `Maximum bet: ${maximumBet} currency`,
            `House edge: ${houseEdge}%`,
        ];
    
        // Part 2: Bet types
        const rules2 = [
            'BET TYPES AND PAYOUTS:',
            '',
            '🔴 RED - Pays 1:1 - Bet on the ball landing on a red number',
            '⚫ BLACK - Pays 1:1 - Bet on the ball landing on a black number',
            '🔢 EVEN - Pays 1:1 - Bet on the ball landing on an even number (not 0)',
            '🔢 ODD - Pays 1:1 - Bet on the ball landing on an odd number',
            '⬆️ HIGH - Pays 1:1 - Bet on the ball landing on numbers 19-36',
            '⬇️ LOW - Pays 1:1 - Bet on the ball landing on numbers 1-18',
            '🎯 NUMBER - Pays 35:1 - Bet on the ball landing on a specific number (0-36)',
        ];
    
        // Part 3: Examples
        const rules3 = [
            'EXAMPLES:',
            '/roulette red 100 - Bet 100 on red',
            '/roulette 17 50 - Bet 50 on the number 17',
            '/roulette black 200 - Bet 200 on black',
            '',
            'Use /roulettestats to view your statistics!'
        ];
    
        // Send messages with a slight delay between them
        await player.pm(rules1.join('\n'));
        await player.pm(rules2.join('\n'));
        await player.pm(rules3.join('\n'));
    }
    
    await main();

Permissions 3

Roles you can grant to decide who may use what.

  • Play Roulette

    Allows the player to place bets and play roulette.

  • Higher Betting Limits

    Allows the player to exceed the normal maximum bet. Count is multiplier for max bet.

  • Roulette Admin

    Allows resetting player statistics and other administrative functions.