Search code examples
javascriptdiscord.jsquick.db

discord.js manual levelling system with quick.db


I'm trying to make a levelling system configured for my server that gives XP to users when admins use >givexp, sends a message when a user reaches a new level, resets a user's XP & levels when admins use >resetxp, and displays the user's level & XP (current XP on the current level over XP to the next level) on using >level.

However, users aren't receiving XP from the first time being awarded XP (if I use >givexp @user#1234 50, then use >givexp @user#1234 20, their total XP would be 20).

A user on Level 0 reaching 100 XP or more after the last awarding won't be given Level 1 until being awarded more XP.

givexp.js:

const Discord = require("discord.js");
const db = require("quick.db")
const adm = " "; //ids here

module.exports = { 
    name: "givexp"
}

module.exports.ex = async(message, args) => {
  let { guild } = message;
  const user = message.mentions.users.first();
    if (message.author.id === adm) {
      if (!user) {
        message.channel.send(new Discord.MessageEmbed().setColor("D9B3FF").setTitle("Invalid Syntax").setDescription(`The format for [givexp] is \`>givexp @user#1234 [amount]\``));
      } else {

        // xp requirements for each level
        const levels = {
          0: 100,
          1: 125,
          2: 150,
          3: 175,
          4: 200,
          5: 225
        };

        // total xp requirements
        const xpreqs = {
          0: 100,
          1: 225,
          2: 350,
          3: 475,
          4: 600,
          5: 725
        }

        const giveAmount = args.slice(1).join(" ");
        let xp = db.get(`xp_${message.guild.id}_${user.id}`);
        let level = db.get(`level_${message.guild.id}_${user.id}`);
        let totalxp = db.get(`totalxp_${message.guild.id}_${user.id}`);

        if (xp === null) db.set(`xp_${message.guild.id}_${user.id}`, 0);
        if (totalxp === null) db.set(`totalxp_${message.guild.id}_${user.id}`, 0);
        if (level === null) db.set(`level_${message.guild.id}_${user.id}`, 0);

        if (giveAmount) {

          await db.add(`totalxp_${message.guild.id}_${user.id}`, parseInt(giveAmount));
          user.send(new Discord.MessageEmbed().setColor("D9B3FF").setDescription(`You were awarded **${giveAmount}XP** by ${message.author.tag}`));
          await message.channel.send(new Discord.MessageEmbed().setColor("D9B3FF").setDescription(`${user.tag} has been awarded **${giveAmount}XP** by ${message.author.tag}`));
          console.log(`${message.author.tag} awarded ${user.tag} ${giveAmount}XP.`);

          if (totalxp >= xpreqs[level]) {

            await db.set(`xp_${message.guild.id}_${user.id}`, totalxp - xpreqs[level]);
            await db.add(`level_${message.guild.id}_${user.id}`, 1);
            level = db.get(`level_${message.guild.id}_${user.id}`);

            await message.channel.send(new Discord.MessageEmbed().setColor("D9B3FF").setTitle("Level Up!").setDescription(`<@${user.id}> has reached Level ${level}!`))

          } else if (totalxp < xpreqs[level]) {

            await db.add(`xp_${message.guild.id}_${user.id}`, parseInt(giveAmount));

          }

        } else {
          message.channel.send(new Discord.MessageEmbed().setColor("D9B3FF").setTitle("Invalid Syntax").setDescription(`The format for [givexp] is \`>givexp @user#1234 [amount]\``));
        }
      }
    } else {
      message.channel.send(new Discord.MessageEmbed().setColor("D9B3FF").setDescription(`<@${message.author.id}>, you do not have permission to give users XP.`));
    }
};

level.js

const Discord = require("discord.js");
const db = require("quick.db")

module.exports = { 
    name: "level"
}

module.exports.ex = async(message, args) => {
  let { guild } = message;
  const user = message.mentions.members.first() || message.author;

  const levels = {
    0: 100,
    1: 125,
    2: 150,
    3: 175,
    4: 200,
    5: 225
  };

  let xp = db.get(`xp_${message.guild.id}_${user.id}`);
  let level = db.get(`level_${message.guild.id}_${user.id}`);
  let xpreq = levels[level];

  if (xp === null) {
    xp = 0;
  }
  if (level === null) {
    level = 0;
  }

  message.channel.send(new Discord.MessageEmbed().setColor("D9B3FF").setAuthor(user.username, message.guild.iconURL()).setThumbnail(user.avatarURL()).setDescription(`**LEVEL: **${level}\n**XP: **${xp}/${xpreq}`));
  console.log(`${message.author.tag} used [level] in ${guild.name}`);
};

Solution

  • It is because if the value is null, like you check it. You never redefine the value of level variable. You just set the level to 0 on your quick.db, but not the actual variable.

    if (level === null) db.set(`level_${message.guild.id}_${user.id}`, 0);
    // this is the issue, "if level is null, set db level_${message.guild.id} to 0"
    

    You need to set the value to the level variable as well so once you check the leveling requirement later on your code

    if (totalxp >= xpreqs[level])
    // You are basically checking if (totalxp >= xpreqs[null])
    

    That is why your users get the level they need after the second XP addition because then there is value for your level variable already.