diff --git a/commands/leaderboard.js b/commands/leaderboard.js index 0541cf1..7fea667 100644 --- a/commands/leaderboard.js +++ b/commands/leaderboard.js @@ -30,6 +30,9 @@ module.exports = { { name: "Longest Kill", value: "longestKill" }, { name: "KDR", value: "KDR" }, { name: "Server Connections", value: "connections" }, + { name: "Shots Landed", value: "shotsLanded" }, + { name: "Times Shot", value: "timesShot" }, + { name: "Combat Rating", value: "combatRating" }, ] }, { name: "limit", @@ -81,7 +84,10 @@ module.exports = { category == 'totalSessionTime' ? "Total Time Played" : category == 'longestSessionTime' ? "Longest Game Session" : category == 'KDR' ? "Kill Death Ratio" : - category == 'connections' ? "Times Connected" : 'N/A Error'; + category == 'connections' ? "Times Connected" : + category == 'shotsLanded' ? "Shots Landed" : + category == 'timesShot' ? "Times Shot" : + category == 'combatRating' ? "Combat Rating" : 'N/A Error'; leaderboardEmbed.setTitle(`**${title} - DayZ Reforger**`); @@ -100,16 +106,17 @@ module.exports = { category == 'totalSessionTime' ? `**Total:** ${client.secondsToDhms(leaderboard[i].totalSessionTime)}\n> **Last Session:** ${client.secondsToDhms(leaderboard[i].lastSessionTime)}` : category == 'longestSessionTime' ? `**Longest Game Session:** ${client.secondsToDhms(leaderboard[i].longestSessionTime)}` : category == 'KDR' ? `**KDR: ${leaderboard[i].KDR.toFixed(2)}**` : - category == 'connection' ? `**Connections: ${leaderboard[i].connections}**` : 'N/A Error'; + category == 'connection' ? `**Connections: ${leaderboard[i].connections}**` : + category == 'combatRating' ? `**Combat Rating:** ${leaderboard[i].combatRating}` : 'N/A Error'; if (category == 'money') des += `**${i+1}.** <@${leaderboard[i].user.userID}> - **${stats}**\n` - else if (category == 'totalSessionTime' || category == 'longestSessionTime') { + else if (category == 'totalSessionTime' || category == 'longestSessionTime' || category == 'combatRating') { tag = leaderboard[i].discordID != "" ? `<@${leaderboard[i].discordID}>` : leaderboard[i].gamertag; des += `**${i+1}.** ${tag}\n> ${stats}\n\n`; } else leaderboardEmbed.addFields({ name: `**${i+1}. ${leaderboard[i].gamertag}**`, value: `**${stats}**`, inline: true }); } - if (['money', 'totalSessionTime', 'longestSessionTime'].includes(category)) leaderboardEmbed.setDescription(des); + if (['money', 'totalSessionTime', 'longestSessionTime', 'combatRating'].includes(category)) leaderboardEmbed.setDescription(des); return interaction.send({ embeds: [leaderboardEmbed] }); }, diff --git a/commands/player-stats.js b/commands/player-stats.js index 7765505..a3cb9f0 100644 --- a/commands/player-stats.js +++ b/commands/player-stats.js @@ -106,7 +106,8 @@ module.exports = { category == 'KDR' ? "Kill Death Ratio" : category == 'connections' ? "Times Connected" : category == 'shotsLanded' ? "Shots Landed" : - category == 'timesShot' ? "Times Shot" : 'N/A Error'; + category == 'timesShot' ? "Times Shot" : + category == 'combatRating' ? "Combat Rating" : 'N/A Error'; let statsEmbed = new EmbedBuilder() .setColor(client.config.Colors.Default); @@ -126,7 +127,8 @@ module.exports = { category == 'longestKill' ? `${query.longestKill}m` : category == 'money' ? `$${(query.user.guilds[GuildDB.serverID].balance).toLocaleString(undefined, {minimumFractionDigits: 2, maximumFractionDigits: 2})}` : category == 'KDR' ? `${query.KDR.toFixed(2)} KDR` : - category == 'connections' ? `${query.connections} connections` : 'N/A Error'; + category == 'connections' ? `${query.connections} connections` : + category == 'combatRating' ? `${query.combatRating}` : 'N/A Error'; statsEmbed.addFields({ name: 'Leaderboard Position', value: `# ${leaderboardPos}`, inline: true }); @@ -200,6 +202,32 @@ module.exports = { statsEmbed.setImage(chartURL); + } else if (category == 'combatRating') { + + statsEmbed.addFields({ name: 'Combat Rating', value: `${query.combatRating}`, inline: true }); + + const chart = { + type: 'bar', + data: { + labels: new Array(query.combatRatingHistory), + datasets: [ + { + type: 'line', + label: 'Combat Rating over time', + borderColor: 'rgb(54, 162, 235)', + borderWidth: 2, + fill: false, + data: query.combatRatingHistory, + }, + ], + }, + } + + const encodedChart = encodeURIComponent(JSON.stringify(chart)); + const chartURL = `https://quickchart.io/chart?c=${encodedChart}`; + + statsEmbed.setImage(chartURL); + } else statsEmbed.addFields({ name: title, value: stats, inline: true }); return interaction.send({ embeds: [statsEmbed] }); diff --git a/database/player.js b/database/player.js index b213d2f..3b03011 100644 --- a/database/player.js +++ b/database/player.js @@ -66,6 +66,8 @@ module.exports = { shotsLandedPerBodyPart: copy(BodyParts), timesShotPerBodyPart: copy(BodyParts), }), + combatRating: 800, + combatRatingHistory: [800], // General Session Data lastConnectionDate: null, diff --git a/package-lock.json b/package-lock.json index 01dd90a..b81e9e4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,13 +1,13 @@ { - "name": "dayz-armbands", - "version": "8.6.0", + "name": "dayzr-bot", + "version": "12.2.0", "lockfileVersion": 2, "requires": true, "packages": { "": { - "name": "dayz-armbands", - "version": "8.6.0", - "license": "ISC", + "name": "dayzr-bot", + "version": "12.2.0", + "license": "MIT", "dependencies": { "@discordjs/rest": "^1.1.0", "colors": "^1.4.0", @@ -17,7 +17,6 @@ "dotenv": "^16.0.3", "form-data": "^4.0.0", "mongodb": "^4.12.1", - "mongoose": "^7.0.1", "winston": "^3.8.1" }, "devDependencies": { @@ -1540,27 +1539,6 @@ "typedarray": "^0.0.6" } }, - "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/debug/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -1807,14 +1785,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/kareem": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.5.1.tgz", - "integrity": "sha512-7jFxRVm+jD+rkq3kY0iZDJfsO2/t4BBPeEb2qKn2lR/9KhuksYk5hxzfRYWMPV8P/x2d0kHD306YyWLzjjH+uA==", - "engines": { - "node": ">=12.0.0" - } - }, "node_modules/kuler": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", @@ -1905,94 +1875,6 @@ "whatwg-url": "^11.0.0" } }, - "node_modules/mongoose": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-7.4.4.tgz", - "integrity": "sha512-LOOviiEqWOLH4PuBK+jbpm5vjBkdSNBcP/4UCevOJMTl5SXSbCXr68ulEYcthLcN2/xi08452HupKD8BfxNIQw==", - "dependencies": { - "bson": "^5.4.0", - "kareem": "2.5.1", - "mongodb": "5.7.0", - "mpath": "0.9.0", - "mquery": "5.0.0", - "ms": "2.1.3", - "sift": "16.0.1" - }, - "engines": { - "node": ">=14.20.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mongoose" - } - }, - "node_modules/mongoose/node_modules/bson": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/bson/-/bson-5.4.0.tgz", - "integrity": "sha512-WRZ5SQI5GfUuKnPTNmAYPiKIof3ORXAF4IRU5UcgmivNIon01rWQlw5RUH954dpu8yGL8T59YShVddIPaU/gFA==", - "engines": { - "node": ">=14.20.1" - } - }, - "node_modules/mongoose/node_modules/mongodb": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-5.7.0.tgz", - "integrity": "sha512-zm82Bq33QbqtxDf58fLWBwTjARK3NSvKYjyz997KSy6hpat0prjeX/kxjbPVyZY60XYPDNETaHkHJI2UCzSLuw==", - "dependencies": { - "bson": "^5.4.0", - "mongodb-connection-string-url": "^2.6.0", - "socks": "^2.7.1" - }, - "engines": { - "node": ">=14.20.1" - }, - "optionalDependencies": { - "saslprep": "^1.0.3" - }, - "peerDependencies": { - "@aws-sdk/credential-providers": "^3.201.0", - "@mongodb-js/zstd": "^1.1.0", - "kerberos": "^2.0.1", - "mongodb-client-encryption": ">=2.3.0 <3", - "snappy": "^7.2.2" - }, - "peerDependenciesMeta": { - "@aws-sdk/credential-providers": { - "optional": true - }, - "@mongodb-js/zstd": { - "optional": true - }, - "kerberos": { - "optional": true - }, - "mongodb-client-encryption": { - "optional": true - }, - "snappy": { - "optional": true - } - } - }, - "node_modules/mpath": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz", - "integrity": "sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew==", - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/mquery": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/mquery/-/mquery-5.0.0.tgz", - "integrity": "sha512-iQMncpmEK8R8ncT8HJGsGc9Dsp8xcgYMVSbs5jgnm1lFHTZqMJTUWTDx1LBO8+mK3tPNZWFLBghQEIOULSTHZg==", - "dependencies": { - "debug": "4.x" - }, - "engines": { - "node": ">=14.0.0" - } - }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -2193,11 +2075,6 @@ "semver": "bin/semver" } }, - "node_modules/sift": { - "version": "16.0.1", - "resolved": "https://registry.npmjs.org/sift/-/sift-16.0.1.tgz", - "integrity": "sha512-Wv6BjQ5zbhW7VFefWusVP33T/EM0vYikCaQ2qR8yULbsilAT8/wQaXvuQ3ptGLpoKx+lihJE3y2UTgKDyyNHZQ==" - }, "node_modules/simple-swizzle": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", @@ -3760,21 +3637,6 @@ "typedarray": "^0.0.6" } }, - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "requires": { - "ms": "2.1.2" - }, - "dependencies": { - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - } - } - }, "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -3949,11 +3811,6 @@ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==" }, - "kareem": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.5.1.tgz", - "integrity": "sha512-7jFxRVm+jD+rkq3kY0iZDJfsO2/t4BBPeEb2qKn2lR/9KhuksYk5hxzfRYWMPV8P/x2d0kHD306YyWLzjjH+uA==" - }, "kuler": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", @@ -4030,51 +3887,6 @@ "whatwg-url": "^11.0.0" } }, - "mongoose": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-7.4.4.tgz", - "integrity": "sha512-LOOviiEqWOLH4PuBK+jbpm5vjBkdSNBcP/4UCevOJMTl5SXSbCXr68ulEYcthLcN2/xi08452HupKD8BfxNIQw==", - "requires": { - "bson": "^5.4.0", - "kareem": "2.5.1", - "mongodb": "5.7.0", - "mpath": "0.9.0", - "mquery": "5.0.0", - "ms": "2.1.3", - "sift": "16.0.1" - }, - "dependencies": { - "bson": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/bson/-/bson-5.4.0.tgz", - "integrity": "sha512-WRZ5SQI5GfUuKnPTNmAYPiKIof3ORXAF4IRU5UcgmivNIon01rWQlw5RUH954dpu8yGL8T59YShVddIPaU/gFA==" - }, - "mongodb": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-5.7.0.tgz", - "integrity": "sha512-zm82Bq33QbqtxDf58fLWBwTjARK3NSvKYjyz997KSy6hpat0prjeX/kxjbPVyZY60XYPDNETaHkHJI2UCzSLuw==", - "requires": { - "bson": "^5.4.0", - "mongodb-connection-string-url": "^2.6.0", - "saslprep": "^1.0.3", - "socks": "^2.7.1" - } - } - } - }, - "mpath": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz", - "integrity": "sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew==" - }, - "mquery": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/mquery/-/mquery-5.0.0.tgz", - "integrity": "sha512-iQMncpmEK8R8ncT8HJGsGc9Dsp8xcgYMVSbs5jgnm1lFHTZqMJTUWTDx1LBO8+mK3tPNZWFLBghQEIOULSTHZg==", - "requires": { - "debug": "4.x" - } - }, "ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -4206,11 +4018,6 @@ "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true }, - "sift": { - "version": "16.0.1", - "resolved": "https://registry.npmjs.org/sift/-/sift-16.0.1.tgz", - "integrity": "sha512-Wv6BjQ5zbhW7VFefWusVP33T/EM0vYikCaQ2qR8yULbsilAT8/wQaXvuQ3ptGLpoKx+lihJE3y2UTgKDyyNHZQ==" - }, "simple-swizzle": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", diff --git a/package.json b/package.json index a0db0ee..b69a385 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dayzr-bot", - "version": "12.1.11", + "version": "12.2.0", "description": "A General Purpose Discord Bot for DayZ Nitrado Servers.", "main": "index.js", "nodemonConfig": { diff --git a/util/KillfeedHandler.js b/util/KillfeedHandler.js index 5a64adf..14da307 100644 --- a/util/KillfeedHandler.js +++ b/util/KillfeedHandler.js @@ -4,6 +4,7 @@ const { KillInAlarm } = require('./AlarmsHandler'); const { destinations } = require('../database/destinations'); const { calculateVector } = require('./vector'); const { getDefaultPlayer, UpdatePlayer } = require('../database/player'); +const { calculateNewCombatRating } = require('./combatRatingHandler'); const Templates = { Killed: 1, @@ -182,6 +183,16 @@ module.exports = { victimStat.killStreak = 0; victimStat.lastDeathDate = newDt; killerStat.deathStreak = 0; + if (!client.exists(killerStat.combatRating)) killerStat.combatRating = 800; + if (!client.exists(victimStat.combatRating)) victimStat.combatRating = 800; + if (!client.exists(killerStat.combatRatingHistory)) killerStat.combatRatingHistory = [800]; + if (!client.exists(victimStat.combatRatingHistory)) victimStat.combatRatingHistory = [800]; + let killerOldRating = killerStat.combatRating; + let victimOldRating = victimStat.combatRating; + killerStat.combatRating = calculateNewCombatRating(killerStat.combatRating, victimStat.combatRating, 1); + victimStat.combatRating = calculateNewCombatRating(victimStat.combatRating, killerStat.combatRating, 0); + let kdiff = killerStat.combatRating - killerOldRating; + let vdiff = victimStat.combatRating - victimOldRating; let receivedBounty = null; if (victimStat.bounties.length > 0 && killerStat.discordID != "") { @@ -228,7 +239,7 @@ module.exports = { const killEvent = new EmbedBuilder() .setColor(client.config.Colors.Default) - .setDescription(`**Kill Event** - \n**${info.killer}** killed **${info.victim}**\n> **__Kill Data__**\n> Weapon: \` ${info.weapon} \`\n> Distance: \` ${info.distance}m \`\n> Body Part: \` ${info.bodyPart != undefined ? info.bodyPart.split('(')[0] : 'N/A'} \`\n> Damage: \` ${info.damage != undefined ? info.damage : 'N/A'} \`\n **Killer**\n${killerStat.KDR.toFixed(2)} K/D - ${killerStat.kills} Kill${(killerStat.kills == 0 || killerStat.kills > 1) ? 's':''} - Killstreak: ${killerStat.killStreak}\n**Victim**\n${victimStat.KDR.toFixed(2)} K/D - ${victimStat.deaths} Death${victimStat.deaths == 0 || victimStat.deaths>1?'s':''} - Deathstreak: ${victimStat.deathStreak}${coord}`); + .setDescription(`**Kill Event** - \n**${info.killer}** killed **${info.victim}**\n> **__Kill Data__**\n> Weapon: \` ${info.weapon} \`\n> Distance: \` ${info.distance}m \`\n> Body Part: \` ${info.bodyPart != undefined ? info.bodyPart.split('(')[0] : 'N/A'} \`\n> Damage: \` ${info.damage != undefined ? info.damage : 'N/A'} \`\n **Killer**\n**${info.killer}'s New Combat Rating:** (${kdiff >= 0 ? '+' : ''}${kdiff}) ${killerStat.combatRating}\n${killerStat.KDR.toFixed(2)} K/D - ${killerStat.kills} Kill${(killerStat.kills == 0 || killerStat.kills > 1) ? 's':''} - Killstreak: ${killerStat.killStreak}\n**Victim**\n**${info.victim}'s New Combat Rating:** (${vdiff >= 0 ? '+' : ''}${vdiff}) ${victimStat.combatRating}\n${victimStat.KDR.toFixed(2)} K/D - ${victimStat.deaths} Death${victimStat.deaths == 0 || victimStat.deaths>1?'s':''} - Deathstreak: ${victimStat.deathStreak}${coord}`); if (client.exists(channel)) await channel.send({ embeds: [killEvent] }); if (client.exists(receivedBounty) && client.exists(channel)) await channel.send({ content: `<@${killerStat.discordID}>`, embeds: [receivedBounty] }); diff --git a/util/combatRatingHandler.js b/util/combatRatingHandler.js new file mode 100644 index 0000000..9f7b0ca --- /dev/null +++ b/util/combatRatingHandler.js @@ -0,0 +1,6 @@ +module.exports = { + calculateNewCombatRating: (Ra, Rb, score) => { + const Ea = 1 / (1 + Math.pow(10, ((Rb - Ra) / 400))); + return Math.round(Ra + 32 * (score - Ea)); + }, +} \ No newline at end of file