Points/Currency System
This points bot is simple, but functional. Make sure you've followed the Installation Instructions before doing the following.
First, you need to create a new persistent Enmap. Here's how it goes:
const Enmap = require("enmap");
client.points = new Enmap({name: "points"});That will create a new Enmap under the name of points, and attaches it to the client object so it can be used where ever you have access to the client object.
Accumulating Points
The obvious goal of a points system is to accumulate fake internet points and gloat about it. So, of course, that's going to be our first focus. In this example implementation, we will make the points guild-specific, and unuseable in DMs. Points will still accumulate even if the user does a command, which simplifies our code a bit.
Our starting point is a very basic message handler with pre-existing commands - such as what we see in the Command with Arguments page on An Idiot's Guide. The code is as such:
client.on("message", message => {
if (message.author.bot) return;
// This is where we'll put our code.
if (message.content.indexOf(config.prefix) !== 0) return;
const args = message.content.slice(config.prefix.length).trim().split(/ +/g);
const command = args.shift().toLowerCase();
// Command-specific code here!
});We do have a small caveat - we really don't want to react on Direct Messages, so our whole code will be in a block that checks for that:
Our very first step is going to be to initialize a new entry in the enmap for any new user - one we haven't received a message from before. This is done using the enmap.ensure(key, defaultvalue) method, which can check if a specific key exists in the Enmap, write it if it doesn't (and return the defaultvalue in this case). Note that our keys take the format of guildid-userid so they're unique to the guild and the user. Also, our data in this case is a complete object, which we'll take advantage of fully.
There's obviously a few ways we could have done this, including some fancy ternary condition or whatever. I will, however, keep this code as simple to read as possible.
The following bit is super simple - Enmap has a method to directly increment a value in Enmap even if it's in an object. Pretty clever if I do say so myself!
Ding!
Time to level up! If a user has enough points, they will go up a level. Now we have to do some math here, but don't run off in fear, this one's pretty easy. This is how we calculate the levels:
This line will calculate the square root of currentPoints then multiplies that result by 0.1 then floors that result for a round number.
Now we should work out if you've amassed enough points to actually level up, by grabbing the current user's level and comparing them. If the new calculated level is higher, it means the user leveled up and we can deal with that, first by sending them a very annoying mee6-inspired message!
Lastly, we want to update the score.level value with the new level so throw this under the message.reply.
So here's the whole thing from top to bottom, with bonus comments!
Points & Level Commands
Alright, that's the bulk of the code, you could throw this into your bot and it would work like a charm, however your users wouldn't know how many points, or even their levels, so let's fix that, make a new command called points, which will also show them their level.
So let's re-iterate our current starting position.
The points command would look like this:
We are the champions, my friend!
Let's finish this off with a very simple leaderboard command that will show the top 10 users in the current guild. For this we'll need to filter the Enmap to only get the users for the current guild, then we'll convert the results to an array, sort that, and keep the first 10 results only.
So here's our leaderboard command:
ADDENDUM: Extra Commands!
Last updated