dailyRewardsItems

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

Provides a comprehensive daily reward system for players, including streak tracking, milestone bonuses, and the chance to earn random items.

  • Daily Rewards: Players can claim a base reward that increases with their daily login streak.
  • Streak Tracking: The module tracks players' consecutive daily logins, encouraging consistent engagement.
  • Milestone Rewards: Configurable bonus rewards are granted to players for reaching specific streak milestones, providing long-term goals.
  • Random Item Rewards: Players have a chance to receive random in-game items as part of their daily reward, with configurable item chances and a streak-based multiplier.
  • Customizable Rewards: The base reward amount, maximum streak, milestone rewards, possible items, and item chances are all configurable.
  • Permission System: Supports permissions to control who can claim rewards and to allow for reward multipliers (e.g., for donors).
  • Player Notifications: Provides in-game messages to inform players about their streak, next claim time, milestones, and rewards.

Configuration 8

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

SettingTypeDefaultDescription
baseReward required Base Reward number 100 Base amount of currency given for daily rewards. This is multiplied by streak level.
maxStreak required Maximum Streak number 365 Maximum streak level a player can reach
milestoneRewards required Milestone Rewards array [{"days":7,"reward":1000,"message":"You did it! 7 days in a row!"},{"days":30,"reward":5000,"message":"A whole month! You're on fire!"},{"days":90,"reward":20000,"message":"90 days! You're unstoppable!"},{"days":180,"reward":50000,"message":"Half a year! You're a legend!"},{"days":365,"reward":150000,"message":"365 days! You're a true champion!"}] Additional rewards for reaching certain streak milestones
possibleItems Possible Items array [] Items that can be randomly awarded as daily rewards
itemChance Base Item Chance string "25" Base chance to receive an item (1-100)
useStreakMultiplier Use Streak Multiplier boolean false Increase the item chance based on player streak
streakMultiplierValue Streak Multiplier Value number 0.5 How much to increase item chance per streak day (e.g. 0.5 = +0.5% per day)
maxItemChance Maximum Item Chance number 95 Cap for total item chance after streak multiplier (1-100)
Raw config schema
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "baseReward": {
      "type": "number",
      "title": "Base Reward",
      "description": "Base amount of currency given for daily rewards. This is multiplied by streak level.",
      "default": 100,
      "minimum": 1
    },
    "maxStreak": {
      "type": "number",
      "title": "Maximum Streak",
      "description": "Maximum streak level a player can reach",
      "default": 365,
      "minimum": 1
    },
    "milestoneRewards": {
      "type": "array",
      "title": "Milestone Rewards",
      "description": "Additional rewards for reaching certain streak milestones",
      "items": {
        "type": "object",
        "properties": {
          "days": {
            "type": "number",
            "description": "Days needed to reach milestone",
            "minimum": 1
          },
          "reward": {
            "type": "number",
            "description": "Bonus reward amount"
          },
          "message": {
            "type": "string",
            "description": "Message to show when milestone is reached"
          }
        }
      },
      "default": [
        {
          "days": 7,
          "reward": 1000,
          "message": "You did it! 7 days in a row!"
        },
        {
          "days": 30,
          "reward": 5000,
          "message": "A whole month! You're on fire!"
        },
        {
          "days": 90,
          "reward": 20000,
          "message": "90 days! You're unstoppable!"
        },
        {
          "days": 180,
          "reward": 50000,
          "message": "Half a year! You're a legend!"
        },
        {
          "days": 365,
          "reward": 150000,
          "message": "365 days! You're a true champion!"
        }
      ]
    },
    "possibleItems": {
      "type": "array",
      "title": "Possible Items",
      "description": "Items that can be randomly awarded as daily rewards",
      "x-component": "item",
      "uniqueItems": true,
      "items": {
        "type": "object",
        "title": "Item",
        "properties": {
          "item": {
            "type": "string",
            "title": "Item"
          },
          "amount": {
            "type": "number",
            "title": "Amount",
            "default": 1
          },
          "quality": {
            "type": "string",
            "title": "Quality"
          }
        }
      },
      "default": []
    },
    "itemChance": {
      "title": "Base Item Chance",
      "description": "Base chance to receive an item (1-100)",
      "type": "string",
      "minLength": 1,
      "maxLength": 100,
      "default": "25"
    },
    "useStreakMultiplier": {
      "title": "Use Streak Multiplier",
      "description": "Increase the item chance based on player streak",
      "type": "boolean",
      "default": false
    },
    "streakMultiplierValue": {
      "title": "Streak Multiplier Value",
      "description": "How much to increase item chance per streak day (e.g. 0.5 = +0.5% per day)",
      "type": "number",
      "default": 0.5,
      "minimum": 0
    },
    "maxItemChance": {
      "title": "Maximum Item Chance",
      "description": "Cap for total item chance after streak multiplier (1-100)",
      "type": "number",
      "default": 95,
      "minimum": 1,
      "maximum": 100
    }
  },
  "required": [
    "baseReward",
    "maxStreak",
    "milestoneRewards"
  ],
  "additionalProperties": false
}
Raw UI schema
{
  "possibleItems": {
    "items": {
      "item": {
        "ui:widget": "item"
      }
    }
  }
}

Commands 3

Chat commands players trigger in game.

  • streak

    Check your current daily reward streak and next claim time

    Command source
    import { data, takaro } from '@takaro/helpers';
    import { getPlayerStreak, getLastClaim, getMultiplier } from './utils.js';
    async function main() {
        const { pog, gameServerId, module: mod } = data;
        const streak = await getPlayerStreak(gameServerId, pog.playerId, mod.moduleId);
        const lastClaim = await getLastClaim(gameServerId, pog.playerId, mod.moduleId);
        const multiplier = await getMultiplier(pog);
        const prefix = (await takaro.settings.settingsControllerGetOne('commandPrefix', gameServerId)).data.data.value;
        if (!streak || !lastClaim) {
            await pog.pm(`You haven't claimed any daily rewards yet! Use ${prefix}daily to get started.`);
            return;
        }
        const nextClaimTime = new Date(lastClaim.getTime() + 24 * 60 * 60 * 1000);
        const now = new Date();
        const canClaim = now >= nextClaimTime;
        // Find next milestone
        let nextMilestone = null;
        for (const milestone of mod.userConfig.milestoneRewards) {
            if (milestone.days > streak) {
                nextMilestone = milestone;
                break;
            }
        }
        let message = `Current streak: ${streak} days${multiplier > 1 ? ` (${multiplier}x donor bonus!)` : ''}\n`;
        message += canClaim
            ? `Your daily reward is available! Use ${prefix}daily to claim it!\n`
            : `Next reward available at: ${nextClaimTime.toLocaleString()}\n`;
        if (nextMilestone) {
            message += `\n🎯 Next milestone: ${nextMilestone.days} days (${nextMilestone.days - streak} days to go!)`;
        }
        await pog.pm(message);
    }
    await main();
    //# sourceMappingURL=streak.js.map
  • daily

    Claim your daily reward

    Command source
    import { takaro, data, TakaroUserError, checkPermission } from '@takaro/helpers';
    import { DAILY_KEY, STREAK_KEY, getMultiplier } from './utils.js';
    
    async function main() {
        const { pog, gameServerId, module: mod } = data;
    
        if (!checkPermission(pog, 'DAILY_CLAIM')) {
            throw new TakaroUserError('You do not have permission to claim daily rewards.');
        }
    
        // Get last claim time
        const lastClaimRes = await takaro.variable.variableControllerSearch({
            filters: {
                key: [DAILY_KEY],
                gameServerId: [gameServerId],
                playerId: [pog.playerId],
                moduleId: [mod.moduleId],
            },
        });
    
        const now = new Date();
        let streak = 1;
    
        if (lastClaimRes.data.data.length > 0) {
            const lastClaim = new Date(JSON.parse(lastClaimRes.data.data[0].value));
            const hoursSinceLastClaim = (now - lastClaim) / (1000 * 60 * 60);
    
            // Check if 24 hours have passed
            if (hoursSinceLastClaim < 24) {
                const nextClaimTime = new Date(lastClaim.getTime() + 24 * 60 * 60 * 1000);
                throw new TakaroUserError(`You can claim your next reward at ${nextClaimTime.toLocaleString()}`);
            }
    
            // Get current streak
            const streakRes = await takaro.variable.variableControllerSearch({
                filters: {
                    key: [STREAK_KEY],
                    gameServerId: [gameServerId],
                    playerId: [pog.playerId],
                    moduleId: [mod.moduleId],
                },
            });
    
            if (streakRes.data.data.length > 0) {
                // If claimed within 48 hours, increment streak
                if (hoursSinceLastClaim < 48) {
                    streak = Math.min(JSON.parse(streakRes.data.data[0].value) + 1, mod.userConfig.maxStreak);
                    await takaro.variable.variableControllerUpdate(streakRes.data.data[0].id, {
                        value: JSON.stringify(streak),
                    });
                } else {
                    // Reset streak if more than 48 hours
                    streak = 1;
                    await takaro.variable.variableControllerUpdate(streakRes.data.data[0].id, {
                        value: JSON.stringify(1),
                    });
                }
            } else {
                // Create new streak record
                await takaro.variable.variableControllerCreate({
                    key: STREAK_KEY,
                    value: JSON.stringify(1),
                    gameServerId,
                    playerId: pog.playerId,
                    moduleId: mod.moduleId,
                });
            }
    
            // Update last claim time
            await takaro.variable.variableControllerUpdate(lastClaimRes.data.data[0].id, {
                value: JSON.stringify(now),
            });
        } else {
            // First time claim
            await takaro.variable.variableControllerCreate({
                key: DAILY_KEY,
                value: JSON.stringify(now),
                gameServerId,
                playerId: pog.playerId,
                moduleId: mod.moduleId,
            });
    
            await takaro.variable.variableControllerCreate({
                key: STREAK_KEY,
                value: JSON.stringify(1),
                gameServerId,
                playerId: pog.playerId,
                moduleId: mod.moduleId,
            });
        }
    
        const multiplier = await getMultiplier(pog);
        const baseReward = mod.userConfig.baseReward * streak * multiplier;
        let bonusReward = 0;
        let milestoneMessage = '';
    
        // Check for milestones
        for (const milestone of mod.userConfig.milestoneRewards) {
            if (streak === milestone.days) {
                bonusReward = milestone.reward;
                milestoneMessage = `\n${milestone.message}`;
                break;
            }
        }
    
        // Award total currency rewards
        const totalReward = baseReward + bonusReward;
        await takaro.playerOnGameserver.playerOnGameServerControllerAddCurrency(gameServerId, pog.playerId, {
            currency: totalReward,
        });
    
        // Get currency name for display
        let currencyName = "coins";
        try {
            const currencySettings = await takaro.settings.settingsControllerGetOne('currencyName', gameServerId);
            if (currencySettings.data.data) {
                currencyName = currencySettings.data.data.value;
            }
        } catch (error) {
            // Use default if setting not found
        }
    
        // Check for item rewards
        let itemMessage = "";
        const possibleItems = mod.userConfig.possibleItems || [];
        let baseItemChance = parseInt(mod.userConfig.itemChance || '0');
    
        // Apply streak multiplier if enabled
        let finalItemChance = baseItemChance;
        let streakBonusMessage = "";
    
        if (mod.userConfig.useStreakMultiplier && streak > 1) {
            const streakBonus = (streak - 1) * mod.userConfig.streakMultiplierValue;
            finalItemChance = Math.min(baseItemChance + streakBonus, mod.userConfig.maxItemChance || 100);
            streakBonusMessage = ` (includes +${streakBonus.toFixed(1)}% streak bonus)`;
        }
    
        // Check for permission override
        const itemChancePermission = checkPermission(pog, 'DAILY_ITEM_CHANCE_OVERRIDE');
        const actualItemChance = itemChancePermission && itemChancePermission.count != null
            ? itemChancePermission.count
            : finalItemChance;
    
        // Determine if player gets an item
        if (possibleItems.length > 0 && Math.random() * 100 < actualItemChance) {
            // Select random item from the list
            const randomItem = possibleItems[Math.floor(Math.random() * possibleItems.length)];
    
            if (randomItem && randomItem.item) {
                try {
                    // Get item details
                    const itemDetails = await takaro.item.itemControllerFindOne(randomItem.item);
                    if (itemDetails && itemDetails.data.data) {
                        // Give item to player
                        await takaro.gameserver.gameServerControllerGiveItem(gameServerId, pog.playerId, {
                            name: itemDetails.data.data.code,
                            amount: randomItem.amount || 1,
                            quality: randomItem.quality || ''
                        });
                        itemMessage = `\nYou also received: ${randomItem.amount || 1}x ${itemDetails.data.data.name}`;
                    }
                } catch (error) {
                    // Failed to give item, continue without item message
                }
            }
        }
    
        let message = `Daily reward claimed! You received ${totalReward} ${currencyName}\n`;
        message += `Current streak: ${streak} days${multiplier > 1 ? ` (${multiplier}x currency bonus!)` : ''}`;
    
        if (possibleItems.length > 0) {
            message += `\nItem chance: ${actualItemChance.toFixed(1)}%${streakBonusMessage}`;
        }
    
        message += itemMessage;
        message += milestoneMessage;
    
        await pog.pm(message);
    }
    
    await main();
  • topstreak

    Shows the players with highest daily reward streaks

    ArgumentTypeDefaultHelp
    count number 5 Number of players to show (max 25)
    Command source
    import { takaro, data } from '@takaro/helpers';
    import { STREAK_KEY } from './utils.js';
    async function main() {
        const { pog, gameServerId, module: mod, arguments: args } = data;
        // Limit count to reasonable number
        const count = Math.min(Math.max(1, args.count), 50);
        // Get all streaks
        const streaksRes = await takaro.variable.variableControllerSearch({
            filters: {
                key: [STREAK_KEY],
                gameServerId: [gameServerId],
                moduleId: [mod.moduleId],
            },
            limit: 1000, // Get all possible streaks
        });
        if (streaksRes.data.data.length === 0) {
            await pog.pm('No players have started their daily streak yet!');
            return;
        }
        // Sort by streak value
        const sortedStreaks = streaksRes.data.data
            .map((record) => ({
            playerId: record.playerId,
            streak: JSON.parse(record.value),
        }))
            .sort((a, b) => b.streak - a.streak)
            .slice(0, count);
        // Get player names
        const playerDetails = await Promise.all(sortedStreaks.map(async (record) => {
            const player = (await takaro.player.playerControllerGetOne(record.playerId)).data.data;
            return {
                name: player.name,
                streak: record.streak,
            };
        }));
        // Build message
        let message = `Top ${count} Daily Streaks:\n\n`;
        playerDetails.forEach((player, index) => {
            message += `${index + 1}. ${player.name}: ${player.streak} days\n`;
        });
        await pog.pm(message);
    }
    await main();
    //# sourceMappingURL=topstreak.js.map

Hooks 1

Code that runs in reaction to a game or Takaro event.

  • dailyLoginCheck

    Hook for player-connected events

    Hook source
    import { data, takaro } from '@takaro/helpers';
    import { getLastClaim } from './utils.js';
    async function main() {
        const { pog, gameServerId, module: mod } = data;
        const prefix = (await takaro.settings.settingsControllerGetOne('commandPrefix', gameServerId)).data.data.value;
        const lastClaim = await getLastClaim(gameServerId, pog.playerId, mod.moduleId);
        // First time player
        if (!lastClaim) {
            await pog.pm(`Welcome! Use ${prefix}daily to claim your first daily reward and start your streak!`);
            return;
        }
        const now = new Date();
        const nextClaimTime = new Date(lastClaim.getTime() + 24 * 60 * 60 * 1000);
        if (now >= nextClaimTime) {
            await pog.pm(`Your daily reward is ready! Use ${prefix}daily to claim it!`);
        }
    }
    await main();
    //# sourceMappingURL=dailyLoginCheck.js.map

Functions 1

Shared helpers the module's commands, hooks and cron jobs import.

  • utils

    Function source
    import { takaro, checkPermission } from '@takaro/helpers';
    export const DAILY_KEY = 'daily_timestamp';
    export const STREAK_KEY = 'daily_streak';
    export async function getMultiplier(pog) {
        const perm = checkPermission(pog, 'DAILY_REWARD_MULTIPLIER');
        if (perm)
            return perm.count;
        return 1;
    }
    export async function getPlayerStreak(gameServerId, playerId, moduleId) {
        const streakRes = await takaro.variable.variableControllerSearch({
            filters: {
                key: [STREAK_KEY],
                gameServerId: [gameServerId],
                playerId: [playerId],
                moduleId: [moduleId],
            },
        });
        return streakRes.data.data.length ? parseInt(JSON.parse(streakRes.data.data[0].value)) : 0;
    }
    export async function getLastClaim(gameServerId, playerId, moduleId) {
        const lastClaimRes = await takaro.variable.variableControllerSearch({
            filters: {
                key: [DAILY_KEY],
                gameServerId: [gameServerId],
                playerId: [playerId],
                moduleId: [moduleId],
            },
        });
        return lastClaimRes.data.data.length ? new Date(JSON.parse(lastClaimRes.data.data[0].value)) : null;
    }
    //# sourceMappingURL=utils.js.map

Permissions 2

Roles you can grant to decide who may use what.

  • Claim Daily Rewards

    Allows the player to claim daily rewards

  • Multiplier

    Control the multiplier per role. This is useful to give your donors a little extra. Count is an integer multiplier.