diff --git a/commands/player-stats.js b/commands/player-stats.js index 223a9ce..0b638b8 100644 --- a/commands/player-stats.js +++ b/commands/player-stats.js @@ -1,5 +1,6 @@ const { EmbedBuilder } = require('discord.js'); const CommandOptions = require('../util/CommandOptionTypes').CommandOptionTypes; +const { insertPVPstats } = require('../database/player'); module.exports = { name: "player-stats", @@ -30,6 +31,8 @@ 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: "discord", @@ -53,15 +56,10 @@ module.exports = { */ run: async (client, interaction, args, { GuildDB }, start) => { let category = args[0].value; - let discord = args[1] && args[1].name == 'discord' ? args[1].value : undefined + let discord = args[1] && args[1].name == 'discord' ? args[1].value : undefined; let gamertag = args[1] && args[1].name == 'gamertag' ? args[1].value : undefined; - - let playerStat; - if (!discord && gamertag) { - playerStat = await client.dbo.collection("players").findOne({"gamertag": gamertag}); - if (playerStat == undefined) return interaction.send({ embeds: [new EmbedBuilder().setColor(client.config.Colors.Yellow).setDescription(`**Not Found** This gamertag \` ${args[0].value} \` cannot be found, the gamertag may be incorrect or this player has not logged onto the server before for at least \` 5 minutes \`.`)] }); - } - + let self = !discord && !gamertag; // searching for self if both discord and gamertag are undefined; + let query; let leaderboard; let leaderboardPos; @@ -72,18 +70,11 @@ module.exports = { { $sort: { [`user.guilds.${GuildDB.serverID}.balance`]: -1 } } ]).toArray(); - if (discord) { // If searching by discord - query = leaderboard.find(u => u.user.userID == discord); + if (discord) query = leaderboard.find(u => u.user.userID == discord); // Searching by discord user + if (gamertag) query = leaderboard.find(u => u.user.userID == playerStat.discordID); // Searching by gamertag + if (self) query = leaderboard.find(u => u.user.userID == interaction.member.user.id); // Searching for self - } else if (gamertag) { // If searching by gamertag - if (playerStat.discordID == "") return interaction.send({ embeds: [new EmbedBuilder().setColor(client.config.Colors.Yellow).setDescription(`**Unlinked** No Discord User has linked to the gamertag \` ${gamertag} \`.`)] }); - query = leaderboard.find(u => u.user.userID == playerStat.discordID); - - } else { // If searching for self - query = leaderboard.find(u => u.user.userID == interaction.member.user.id); - } - - if (query == undefined) return interaction.send({ embeds: [new EmbedBuilder().setColor(client.config.Colors.Yellow).setDescription(`**Not Found** Unable to find any records with the gamertag or user provided.`)] }); + if (!client.exists(query)) return interaction.send({ embeds: [new EmbedBuilder().setColor(client.config.Colors.Yellow).setDescription(`**Not Found** Unable to find any records with the gamertag or user provided.`)] }); leaderboardPos = leaderboard.indexOf(query); } else { @@ -92,17 +83,11 @@ module.exports = { { $sort: { [`${category}`]: -1 } } ]).toArray(); - if (discord) { // If searching by discord - query = leaderboard.find(s => s.discordID == discord); + if (discord) query = leaderboard.find(s => s.discordID == discord); // Searching by discord user + if (gamertag) query = leaderboard.find(s => s.gamertag == gamertag); // Searching by gamertag + if (self) query = leaderboard.find(s => s.discordID == interaction.member.user.id); // Searching for self - } else if (gamertag ) { // If searching by gamertag - query = leaderboard.find(s => s.gamertag == gamertag); - - } else { // If searching for self - query = leaderboard.find(s => s.discordID == interaction.member.user.id); - } - - if (query == undefined) return interaction.send({ embeds: [new EmbedBuilder().setColor(client.config.Colors.Yellow).setDescription(`**Not Found** Unable to find any records with the gamertag or user provided.`)] }); + if (!client.exists(query)) return interaction.send({ embeds: [new EmbedBuilder().setColor(client.config.Colors.Yellow).setDescription(`**Not Found** Unable to find any records with the gamertag or user provided.`)] }); leaderboardPos = leaderboard.indexOf(query); } @@ -119,7 +104,9 @@ 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" : 'N/A Error'; let statsEmbed = new EmbedBuilder() .setColor(client.config.Colors.Default); @@ -130,7 +117,6 @@ module.exports = { statsEmbed.setDescription(`${tag}'s ${title}`); - let des = ``; let stats = category == 'kills' ? `${query.kills} Kill${(query.kills>1||query.kills==0)?'s':''}` : category == 'killStreak' ? `${query.killStreak} Player Killstreak` : category == 'bestKillStreak' ? `${query.bestKillStreak} Player Killstreak` : @@ -144,6 +130,8 @@ module.exports = { statsEmbed.addFields({ name: 'Leaderboard Position', value: `# ${leaderboardPos}`, inline: true }); + if ((category == 'shotsLanded' || category == 'timesShot') && !client.exists(query.shotsLanded)) query = insertPVPstats(query); + if (category == 'total_time_played') { statsEmbed.addFields( { name: 'Total Time Played', value: client.secondsToDhms(query.totalSessionTime), inline: true }, @@ -154,6 +142,64 @@ module.exports = { { name: 'Longest Game Session', value: client.secondsToDhms(query.longestSessionTime), inline: true }, { name: 'Last Session Time', value: client.secondsToDhms(query.lastSessionTime), inline: true } ); + } else if (category == 'shotsLanded') { + statsEmbed.addFields( + { name: 'Total Shots Landed', value: `${query.shotsLanded}`, inline: true }, + { name: 'View Weapon stats', value: ``, inline: true } + ); + + const chart = { + type: 'bar', + data: { + labels: ['Head', 'Torso', 'Left Arm', 'Right Arm', 'Left Leg', 'Right Leg'], + datasets: [{ + label: 'Shots Landed', + data: [ + query.shotsLandedPerBodyPart.Head, + query.shotsLandedPerBodyPart.Torso, + query.shotsLandedPerBodyPart.LeftArm, + query.shotsLandedPerBodyPart.RightArm, + query.shotsLandedPerBodyPart.LeftLeg, + query.shotsLandedPerBodyPart.RightLeg, + ], + }], + }, + }; + + const encodedChart = encodeURIComponent(JSON.stringify(chart)); + const chartURL = `https://quickchart.io/chart?c=${encodedChart}`; + + statsEmbed.setImage(chartURL); + + } else if (category == 'timesShot') { + statsEmbed.addFields( + { name: 'Total Times Shot', value: `${query.timesShot}`, inline: true }, + { name: 'View Weapon stats', value: ``, inline: true }, + ); + + const chart = { + type: 'bar', + data: { + labels: ['Head', 'Torso', 'Left Arm', 'Right Arm', 'Left Leg', 'Right Leg'], + datasets: [{ + label: 'Times Shot', + data: [ + query.timesShotPerBoduPart.Head, + query.timesShotPerBoduPart.Torso, + query.timesShotPerBoduPart.LeftArm, + query.timesShotPerBoduPart.RightArm, + query.timesShotPerBoduPart.LeftLeg, + query.timesShotPerBoduPart.RightLeg, + ], + }], + }, + }; + + 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/commands/weapon-stats.js b/commands/weapon-stats.js new file mode 100644 index 0000000..5fb2f7c --- /dev/null +++ b/commands/weapon-stats.js @@ -0,0 +1,151 @@ +const { EmbedBuilder, ActionRowBuilder, StringSelectMenuBuilder } = require('discord.js'); +const CommandOptions = require('../util/CommandOptionTypes').CommandOptionTypes; +const { weapons } = require('../database/weapons'); +const { insertPVPstats } = require('../database/player'); + +module.exports = { + name: "weapon-stats", + debug: false, + global: false, + description: "Check player statistics", + usage: "[category] [user or gamertag]", + permissions: { + channel: ["VIEW_CHANNEL", "SEND_MESSAGES", "EMBED_LINKS"], + member: [], + }, + options: [{ + name: "category", + description: "Weapon Category", + value: "category", + type: CommandOptions.String, + required: true, + choices: [ + { name: "Handguns", value: "handguns" }, + { name: "Shotguns", value: "shotguns" }, + { name: "Submachine Guns", value: "subMachineGuns" }, + { name: "Assault Rifles", value: "assaultRifles" }, + { name: "Battle Rifles", value: "battleRifles" }, + { name: "Bolt-action Rifles", value: "boltActionRifles" }, + { name: "Break-action Rifles", value: "breakActionRifles" }, + { name: "Lever-action Rifles", value: "leverActionRifles" }, + { name: "Marksman Rifles", value: "marksmanRifles" }, + { name: "Semi-automatic Rifles", value: "semiAutomaticRifles" }, + { name: "Other", value: "other" }, + ] + }, { + name: "discord", + description: "discord user to lookup stats", + value: "discord", + type: CommandOptions.User, + required: false, + }, { + name: "gamertag", + description: "gamertag to lookup stats", + type: CommandOptions.String, + required: false, + }], + SlashCommand: { + /** + * + * @param {require("../structures/DayzRBot")} client + * @param {import("discord.js").Message} message + * @param {string[]} args + * @param {*} param3 + */ + run: async (client, interaction, args, { GuildDB }) => { + let discord = args[1] && args[1].name == 'discord' ? args[1].value : undefined; + let gamertag = args[1] && args[1].name == 'gamertag' ? args[1].value : undefined; + let self = !discord && !gamertag; // searching for self if both discord and gamertag are undefined + const weaponClass = args[0].value; + + let query; + + // Searching by Discord + if (discord) query = await client.dbo.collection("players").findOne({"discordID": discord}); + + // Searching by Gamertag + if (gamertag) query = await client.dbo.collection("players").findOne({"gamertag": gamertag}); + + // Searching for self + if (self) query = await client.dbo.collection("players").findOne({"discordID": interaction.member.user.id}); + + if (!client.exists(query)) return interaction.send({ embeds: [new EmbedBuilder().setColor(client.config.Colors.Yellow).setDescription(`**Not Found** Unable to find any records with the gamertag or user provided.`)] }); + + let weaponSelect = new StringSelectMenuBuilder() + .setCustomId(`ViewWeaponStats-${query.playerID}-${interaction.member.user.id}`) + .setPlaceholder(`Select an weapon to view stat.`) + + for (const [name, _] of Object.entries(weapons[weaponClass])) { + weaponSelect.addOptions({ + label: name, + description: `View this weapon's stats.`, + value: name, + }); + } + + const opt = new ActionRowBuilder().addComponents(weaponSelect); + + return interaction.send({ components: [opt] }); + }, + }, + + Interactions: { + ViewWeaponStats: { + run: async(client, interaction, GuildDB) => { + if (!interaction.customId.endsWith(interaction.member.user.id)) + return interaction.reply({ content: 'This interaction is not for you', flags: (1 << 6) }); + + const weapon = interaction.values[0]; + const playerID = interaction.customId.split('-')[1]; + let player = await client.dbo.collection("players").findOne({"playerID": playerID}); + const tag = player.discordID != "" ? `<@${player.discordID}>'s` : `**${player.gamertag}'s**>`; + + if (!client.exists(player.shotsLanded)) player = insertPVPstats(player); + + let stats = new EmbedBuilder() + .setColor(client.config.Colors.Default) + .setDescription(`${tag} stats for the ${weapon}`) + .setThumbnail(weapons[weapon]) + .addFields( + { name: `Shots Landed`, value: `${player.weaponStats[weapon].shotsLanded}`, inline: true }, + { name: `Times Shot`, value: `${player.weaponStats[weapon].timesShot}`, inline: true }, + ); + + const chart = { + type: 'bar', + data: { + labels: ['Head', 'Torso', 'Left Arm', 'Right Arm', 'Left Leg', 'Right Leg'], + datasets: [{ + label: `Shots landed with a ${weapon}`, + data: [ + player.shotsLandedPerBodyPart.Head, + player.shotsLandedPerBodyPart.Torso, + player.shotsLandedPerBodyPart.LeftArm, + player.shotsLandedPerBodyPart.RightArm, + player.shotsLandedPerBodyPart.LeftLeg, + player.shotsLandedPerBodyPart.RightLeg, + ], + }, { + label: `Times Shot by a ${weapon}`, + data: [ + player.timesShotPerBodyPart.Head, + player.timesShotPerBodyPart.Torso, + player.timesShotPerBodyPart.LeftArm, + player.timesShotPerBodyPart.RightArm, + player.timesShotPerBodyPart.LeftLeg, + player.timesShotPerBodyPart.RightLeg, + ], + }], + }, + }; + + const encodedChart = encodeURIComponent(JSON.stringify(chart)); + const chartURL = `https://quickchart.io/chart?c=${encodedChart}`; + + stats.setImage(chartURL); + + return interaction.update({ components: [], embeds: [stats] }); + } + } + } +} diff --git a/database/player.js b/database/player.js index 0bfbc41..123fa8c 100644 --- a/database/player.js +++ b/database/player.js @@ -1,3 +1,27 @@ +const { weapons } = require('./weapons'); + +// Creates a copy of an object to prevent mutation of parent (i.e BodyParts, createWeaponsObject) +const copy = (obj) => JSON.parse(JSON.stringify(obj)); + +const BodyParts = { + Head: 0, + Torso: 0, + RightArm: 0, + LeftArm: 0, + RightLeg: 0, + LeftLeg: 0, +}; + +const createWeaponsObject = (value) => { + const defaultWeapons = {}; + for (const [_, weaponNames] of Object.entries(weapons)) { + for (const [name, _] of Object.entries(weaponNames)) { + defaultWeapons[name] = value; + } + } + return copy(defaultWeapons); +}; + module.exports = { UpdatePlayer: async (client, player, interaction=null) => { return await client.dbo.collection("players").updateOne({"playerID": player.playerID}, {$set: player}, (err, _) => { @@ -10,38 +34,68 @@ module.exports = { getDefaultPlayer(gt, pID, NSID) { return { - gamertag: gt, - playerID: pID, - discordID: "", - nitradoServerID: NSID, + // Identifiers + gamertag: gt, + playerID: pID, + discordID: "", + nitradoServerID: NSID, - KDR: 0.00, - kills: 0, - deaths: 0, - killStreak: 0, - bestKillStreak: 0, - longestKill: 0, - deathStreak: 0, - worstDeathStreak: 0, + // General PVP Stats + KDR: 0.00, + kills: 0, + deaths: 0, + killStreak: 0, + bestKillStreak: 0, + longestKill: 0, + deathStreak: 0, + worstDeathStreak: 0, - pos: [], - lastPos: [], - time: null, - lastTime: null, + // In depth PVP Stats + shotsLanded: 0, + timesShot: 0, + shotsLandedPerBodyPart: copy(BodyParts), + timesShotPerBodyPart: copy(BodyParts), + weaponStats: createWeaponsObject({ + shotsLanded: 0, + timesShot: 0, + shotsLandedPerBodyPart: copy(BodyParts), + timesShotPerBodyPart: copy(BodyParts), + }), - lastConnectionDate: null, - lastDisconnectionDate: null, - lastDamageDate: null, - lastDeathDate: null, - lastHitBy: null, - connected: false, + // General Session Data + lastConnectionDate: null, + lastDisconnectionDate: null, + lastDamageDate: null, + lastDeathDate: null, + lastHitBy: null, + connected: false, + pos: [], + lastPos: [], + time: null, + lastTime: null, - totalSessionTime: 0, - lastSessionTime: 0, - longestSessionTime: 0, - connections: 0, - - bounties: [], + // Session Stats + totalSessionTime: 0, + lastSessionTime: 0, + longestSessionTime: 0, + connections: 0, + + // Other + bounties: [], } + }, + + insertPVPstats(player) { + player.shotsLanded = 0; + player.timesShot = 0; + player.shotsLandedPerBodyPart = copy(BodyParts); + player.timesShotPerBodyPart = copy(BodyParts); + player.weaponStats = createWeaponsObject({ + shotsLanded: 0, + timesShot: 0, + shotsLandedPerBodyPart: copy(BodyParts), + timesShotPerBodyPart: copy(BodyParts), + }); + return player; } -} \ No newline at end of file +} diff --git a/database/weapons.js b/database/weapons.js new file mode 100644 index 0000000..ddc2453 --- /dev/null +++ b/database/weapons.js @@ -0,0 +1,72 @@ +module.exports = { + weapons: { + handguns: { + "CR-75": "https://static.wikia.nocookie.net/dayz_gamepedia/images/4/40/CZ75.png/revision/latest/scale-to-width-down/112?cb=20210505021307", + "Deagle": "https://static.wikia.nocookie.net/dayz_gamepedia/images/6/62/Deagle.png/revision/latest/scale-to-width-down/127?cb=20210512003023", + "Derringer": "https://static.wikia.nocookie.net/dayz_gamepedia/images/9/9f/Derringer_Black.png/revision/latest/scale-to-width-down/105?cb=20220521175445", + "FX-45": "https://static.wikia.nocookie.net/dayz_gamepedia/images/f/fd/FNX45.png/revision/latest/scale-to-width-down/104?cb=20210505025055", + "IJ-70": "https://static.wikia.nocookie.net/dayz_gamepedia/images/2/26/MakarovIJ70.png/revision/latest/scale-to-width-down/92?cb=20210209000551", + "Kolt 1911": "https://static.wikia.nocookie.net/dayz_gamepedia/images/f/f9/Colt1911.png/revision/latest/scale-to-width-down/112?cb=20210505030200", + "Engraved Kolt 1911": "https://static.wikia.nocookie.net/dayz_gamepedia/images/2/2a/Engraved1911.png/revision/latest/scale-to-width-down/112?cb=20210505030259", + "Longhorn": "https://static.wikia.nocookie.net/dayz_gamepedia/images/7/79/Longhorn.png/revision/latest/scale-to-width-down/222?cb=20220324214533", + "MK II": "https://static.wikia.nocookie.net/dayz_gamepedia/images/0/0d/MKII.png/revision/latest/scale-to-width-down/171?cb=20210210153348", + "Mlock-91": "https://static.wikia.nocookie.net/dayz_gamepedia/images/9/9b/Glock19.png/revision/latest/scale-to-width-down/121?cb=20210505024259", + "P1": "https://static.wikia.nocookie.net/dayz_gamepedia/images/c/cc/P1.png/revision/latest/scale-to-width-down/120?cb=20220518204515", + "Revolver": "https://static.wikia.nocookie.net/dayz_gamepedia/images/6/6d/Revolver.png/revision/latest/scale-to-width-down/148?cb=20210208232303", + "Signal Pistol": "https://static.wikia.nocookie.net/dayz_gamepedia/images/a/a7/Flaregun.png/revision/latest/scale-to-width-down/107?cb=20210501150913", + }, + shotguns: { + "BK-133": "https://static.wikia.nocookie.net/dayz_gamepedia/images/5/5c/MP-133-Shotgun.png/revision/latest/scale-to-width-down/256?cb=20210210190104", + "BK-43": "https://static.wikia.nocookie.net/dayz_gamepedia/images/c/c7/Izh43Shotgun.png/revision/latest/scale-to-width-down/256?cb=20210210185835", + "Vaiga": "https://static.wikia.nocookie.net/dayz_gamepedia/images/c/c8/Vaiga.png/revision/latest/scale-to-width-down/256?cb=20220220185225", + }, + subMachineGuns: { + "Bizon": "https://static.wikia.nocookie.net/dayz_gamepedia/images/a/af/PP19.png/revision/latest/scale-to-width-down/251?cb=20220127132305", + "CR-61 Skorpion": "https://static.wikia.nocookie.net/dayz_gamepedia/images/6/63/VZ61Scorpion.png/revision/latest/scale-to-width-down/222?cb=20220518204508", + "SG5-K": "https://static.wikia.nocookie.net/dayz_gamepedia/images/f/fc/MP5-K.png/revision/latest/scale-to-width-down/158?cb=20220221011343", + "USG-45": "https://static.wikia.nocookie.net/dayz_gamepedia/images/d/d7/UMP45.png/revision/latest/scale-to-width-down/153?cb=20220221002354", + }, + assaultRifles: { + "AUR A1": "https://static.wikia.nocookie.net/dayz_gamepedia/images/e/e6/AugShort.png/revision/latest/scale-to-width-down/173?cb=20211104175243", + "AUR AX": "https://static.wikia.nocookie.net/dayz_gamepedia/images/b/be/Aug.png/revision/latest/scale-to-width-down/233?cb=20211104182427", + "KA-101": "https://static.wikia.nocookie.net/dayz_gamepedia/images/f/f2/AK101.png/revision/latest/scale-to-width-down/251?cb=20210207040122", + "KA-74": "https://static.wikia.nocookie.net/dayz_gamepedia/images/8/8b/AK74.png/revision/latest/scale-to-width-down/253?cb=20210505013141", + "KAS-74U": "https://static.wikia.nocookie.net/dayz_gamepedia/images/0/0b/AKS74U.png/revision/latest/scale-to-width-down/191?cb=20210505014222", + "KA-M": "https://static.wikia.nocookie.net/dayz_gamepedia/images/6/6c/AKM.png/revision/latest/scale-to-width-down/244?cb=20210505011614", + "LE-MAS": "https://static.wikia.nocookie.net/dayz_gamepedia/images/2/21/FAMAS.png/revision/latest/scale-to-width-down/197?cb=20210902183114", + "M16-A2": "https://static.wikia.nocookie.net/dayz_gamepedia/images/b/b3/M16-A2.png/revision/latest/scale-to-width-down/256?cb=20220221002601", + "M4-A1": "https://static.wikia.nocookie.net/dayz_gamepedia/images/a/a1/M4A1.png/revision/latest/scale-to-width-down/223?cb=20220330014851", + "SVAL": "https://static.wikia.nocookie.net/dayz_gamepedia/images/3/39/ASVAL.png/revision/latest/scale-to-width-down/256?cb=20210208015731", + }, + battleRifles: { + "LAR": "https://static.wikia.nocookie.net/dayz_gamepedia/images/e/e9/FAL.png/revision/latest/scale-to-width-down/256?cb=20220221001123", + }, + boltActionRifles: { + "CR-527": "https://static.wikia.nocookie.net/dayz_gamepedia/images/f/f0/CR527Wood.png/revision/latest/scale-to-width-down/256?cb=20220518204503 ", + "CR-550 Savanna": "https://static.wikia.nocookie.net/dayz_gamepedia/images/4/44/CR-550_Savanna.png/revision/latest/scale-to-width-down/256?cb=20220518204410", + "M70 Tundra": "https://static.wikia.nocookie.net/dayz_gamepedia/images/6/62/Winchester70.png/revision/latest/scale-to-width-down/256?cb=20220517152918", + "Mosin 91/30": "https://static.wikia.nocookie.net/dayz_gamepedia/images/a/a8/Mosin9130.png/revision/latest/scale-to-width-down/256?cb=20230126021955", + "Pioneer": "https://static.wikia.nocookie.net/dayz_gamepedia/images/6/69/Scout.png/revision/latest/scale-to-width-down/256?cb=20220518204357", + "SSG 82": "https://static.wikia.nocookie.net/dayz_gamepedia/images/1/10/SSG82.png/revision/latest/scale-to-width-down/256?cb=20220922192455", + }, + breakActionRifles: { + "BK-18": "https://static.wikia.nocookie.net/dayz_gamepedia/images/c/cb/IZH18_Rifle.png/revision/latest/scale-to-width-down/256?cb=20220517154121", + "Blaze": "https://static.wikia.nocookie.net/dayz_gamepedia/images/8/8a/Blaze_95_Double_Rifle_Wood.png/revision/latest/scale-to-width-down/256?cb=20220517154129", + }, + leverActionRifles: { + "Repeater Carbine": "https://static.wikia.nocookie.net/dayz_gamepedia/images/c/ce/Repeater.png/revision/latest/scale-to-width-down/256?cb=20220517154151", + }, + marksmanRifles: { + "VSD": "https://static.wikia.nocookie.net/dayz_gamepedia/images/a/a2/SVD_w._PSO-1.png/revision/latest/scale-to-width-down/256?cb=20220220235826", + "VSS": "https://static.wikia.nocookie.net/dayz_gamepedia/images/8/83/VSSVintorez.png/revision/latest/scale-to-width-down/256?cb=20210208202042", + }, + semiAutomaticRifles: { + "SK 59/66": "https://static.wikia.nocookie.net/dayz_gamepedia/images/f/fe/SKS.png/revision/latest/scale-to-width-down/256?cb=20220517154633", + "Sporter 22": "https://static.wikia.nocookie.net/dayz_gamepedia/images/5/5b/Sporter_22_Wood.png/revision/latest/scale-to-width-down/256?cb=20220518204154", + }, + other: { + "Crossbow": "https://static.wikia.nocookie.net/dayz_gamepedia/images/7/79/Crossbow.png/revision/latest/scale-to-width-down/212?cb=20180121164101", + "M79": "https://static.wikia.nocookie.net/dayz_gamepedia/images/b/b7/M79.png/revision/latest/scale-to-width-down/256?cb=20220521184052", + }, + }, +} \ No newline at end of file diff --git a/package.json b/package.json index ab1c92a..ade6486 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dayzr-bot", - "version": "12.0.8", + "version": "12.1.0", "description": "A General Purpose Discord Bot for DayZ Nitrado Servers.", "main": "index.js", "nodemonConfig": { diff --git a/util/LogsHandler.js b/util/LogsHandler.js index 9750b7d..074f03b 100644 --- a/util/LogsHandler.js +++ b/util/LogsHandler.js @@ -3,7 +3,7 @@ const { HandleAlarmsAndUAVs } = require('./AlarmsHandler'); const { SendConnectionLogs, DetectCombatLog } = require('./AdminLogsHandler'); const { getDefaultPlayer } = require('../database/player'); const { FetchServerSettings } = require('../util/NitradoAPI'); -const { UpdatePlayer } = require('../database/player') +const { UpdatePlayer, insertPVPstats } = require('../database/player') let lastSendMessage; @@ -60,7 +60,6 @@ module.exports = { }); await UpdatePlayer(client, playerStat); - return; } if (line.includes(' disconnected')) { @@ -114,7 +113,6 @@ module.exports = { } await UpdatePlayer(client, playerStat); - return; } if (line.includes('pos=<') && !line.includes('hit by')) { @@ -150,7 +148,7 @@ module.exports = { pos: info.pos, }); - return await UpdatePlayer(client, playerStat) + await UpdatePlayer(client, playerStat) } if (line.includes('hit by Player')) { @@ -158,23 +156,44 @@ module.exports = { if (!data) return; const info = { - time: data[1], - player: data[2], - playerID: data[3], - attacker: data[6], - attackerID: data[7] + time: data[1], + player: data[2], + playerID: data[3], + attacker: data[6], + attackerID: data[7], + bodyPart: data[9], + weapon: data[12], }; - if (!client.exists(info.player) || !client.exists(info.playerID)) return; + if (!client.exists(info.player) || !client.exists(info.playerID) || !client.exists(info.attacker) || !client.exists(info.attackerID)) return; let playerStat = await client.dbo.collection("players").findOne({"playerID": info.playerID}); + let attackerStat = await client.dbo.collection("players").findOne({"playerID": info.attackerID}); if (!client.exists(playerStat)) playerStat = getDefaultPlayer(info.player, info.playerID, client.config.Nitrado.ServerID); + if (!client.exists(attackerStat)) attackerStat = getDefaultPlayer(info.attacker, info.attackerID, client.config.Nitrado.ServerID); playerStat.lastDamageDate = await client.getDateEST(info.time); playerStat.lastHitBy = info.attacker; + if (!client.exists(playerStat.shotsLanded)) playerStat = insertPVPstats(playerStat); + if (!client.exists(attackerStat.shotsLanded)) attackerStat = insertPVPstats(attackerStat); + + // Update in depth PVP stats if non Melee weapon\ + if (info.weapon.includes("Sawed-off")) info.weapon = info.weapon.split("Sawed-off ")[1]; + if (info.weapon in playerStat.weaponStats) { + playerStat.timesShot++; + playerStat.timesShotPerBodyPart[info.bodyPart]++; + playerStat.weaponStats[info.weapon].timesShot++; + playerStat.weaponStats[info.weapon].timesShotPerBodyPart[info.bodyPart]++; + + attackerStat.shotsLanded++; + attackerStat.shotsLandedPerBodyPart[info.bodyPart]++; + attackerStat.weaponStats[info.weapon].shotsLanded++; + attackerStat.weaponStats[info,weapon].shotsLandedPerBodyPart[info.bodyPart]++; + } + await UpdatePlayer(client, playerStat); - return; + await UpdatePlayer(client, attackerStat); } return;