stats.js (7914B)
1 const common = require("../../util/functions/common"); 2 const data = require("../../util/Data/data.json"); 3 const { EmbedBuilder } = require("discord.js"); 4 5 let currGun, 6 currStats, 7 currAttachments, 8 currRecoilArr, 9 currDRM, 10 interpretion, 11 recoilAvailable, 12 chart, 13 hasError; 14 module.exports = { 15 name: "stats", 16 description: "Check gun statistics", 17 usage: "(Gun)", 18 category: "CODM", 19 options: [ 20 { 21 type: 3, 22 name: "gun_name", 23 description: "Name of the gun", 24 required: true, 25 choices: [], 26 }, 27 { 28 type: 3, 29 name: "1st_attchment", 30 description: "First attachment", 31 }, 32 { 33 type: 3, 34 name: "2nd_attchment", 35 description: "Second attachment", 36 }, 37 { 38 type: 3, 39 name: "3rd_attchment", 40 description: "Third attachment", 41 }, 42 { 43 type: 3, 44 name: "4th_attchment", 45 description: "Forth attachment", 46 }, 47 { 48 type: 3, 49 name: "5th_attchment", 50 description: "Fifth attachment", 51 }, 52 ], 53 run: async (client, interaction, args) => { 54 repEmb = null; 55 recoilAvailable = false; 56 hasError = false; 57 if (args.length == 1) 58 repEmb = statsHandler(args.join(" ").replace("\n", " ")); 59 else repEmb = statsHandler(args.join(" + ").replace("\n", " ")); 60 if (hasError) { 61 interaction.followUp({ 62 content: `**${repEmb || "An error has occured"}**`, 63 }); 64 } else { 65 if (recoilAvailable) { 66 repEmb.fields.push({ 67 name: "**Recoil Graph**", 68 value: 69 "```\nThe Recoil graph below is dynamic (change based on attachment equipped)```", 70 }); 71 const recoilImageLink = await chart.getShortUrl(); 72 repEmb.image = { url: recoilImageLink }; 73 } 74 interaction.followUp({ embeds: [new EmbedBuilder(repEmb)] }); 75 } 76 }, 77 }; 78 79 function inpHandler(inpmsg) { 80 statsHandler(inpmsg.split("+")[0]); 81 } 82 83 function statsHandler(inpmsg) { 84 let statsNames = [ 85 "Pellets", //0 86 "Detonation Range", //1 87 "Explosion Radius", //2 88 "Explosion Damage", //3 89 "Firing Mode", //4 90 "Rate of Fire", //5 91 "Bullet in Burst", //6 92 "Time Between Burst", //7 93 "Bullet Speed", //8 94 "Penetration Level", //9 95 "Bullet Spread", //10 96 "Idle Sway", //11 97 "Hipfire Pellet Spread", //12 98 "ADS Pellet Spread", //13 99 "ADS Time", //14 100 "Sprint-to-Fire Time", //15 101 "ADS Zoom", //16 102 "Magazine", //17 103 "Reserve", //18 104 "Reload Type", //19 105 "Cancel Reload Time", //20 106 "Reload Time", //21 107 "Full Reload Time", //22 108 "Drop Time", //23 109 "Raise Time", //24 110 "Sprinting Speed", //25 111 "Walking Speed", //26 112 "Straifing Speed", //27 113 "Damage per Tick", //28 114 "Number of Ticks", //29 115 "Time Between Ticks", //30 116 "Breath Hold Time", //31 117 "shouldNeverHappen0", 118 "shouldNeverHappen1", 119 "shouldNeverHappen2", 120 "shouldNeverHappen3", 121 "shouldNeverHappen4", 122 ], 123 out = []; 124 125 currGun = common.weaponIdentifier(inpmsg); 126 if (typeof currGun == "string") { 127 hasError = true; 128 return currGun; 129 } 130 currStats = currGun.stats; 131 currDRM = currGun.drm[0]; // base mag. currGun.drm[1] for more vairents 132 currAttachments = []; 133 currAttachments = common.attachmentsIdentifier(inpmsg, currGun); 134 if (typeof currAttachments == "string") { 135 hasError = true; 136 return currAttachments; 137 } 138 currRecoilArr = [1, 1, currGun.stats[17]]; 139 if (currAttachments.length != 0) { 140 const totalEffects = common.totaler(currAttachments); 141 142 currStats = common.updateStatswithEffects(totalEffects, currStats); 143 currRecoilArr = [totalEffects[2], totalEffects[3], currGun.stats[17]]; // must happen after currStats update 144 currDRM = currGun.drm[totalEffects[37]]; 145 currDRM.range = currDRM.range.map(x => 146 Math.round(x * (1 + totalEffects[13] / 100)) 147 ); 148 out = common.attachmentHandler(totalEffects, currStats); 149 } 150 function statsWorker() { 151 if (currStats[19] === 2) { 152 currStats[21] = 153 currStats[20] + currStats[21] * currStats[17] + currStats[22]; 154 currStats[20] = 0; 155 currStats[22] = 0; 156 } 157 currStats[25] = (currStats[25] * currStats[26]) / 100; 158 159 const outReady = currStats.map((x, i) => 160 x ? statsNames[i].padEnd(24) + ":".padEnd(3) + beautifier(i) : "" 161 ); 162 out = [ 163 ...[ 164 "Basic Stats", 165 "ADS Stats", 166 "Bullet Stats", 167 "Magazine", 168 "Handling Stats", 169 "Mobility Stats", 170 "Miscellaneous Stats", 171 ].map((x, i) => 172 fieldMaker( 173 x, 174 [ 175 [04, 05, 09], 176 [14, 16, 11, 31], 177 [00, 06, 07, 08, 10, 12, 13], 178 [17, 18, 19, 20, 21, 22], 179 [23, 24], 180 [25, 26, 27, 15], 181 [28, 29, 30, 01, 02, 03], 182 ][i] 183 ) 184 ), 185 ...out, 186 ]; 187 function fieldMaker(inpName, inpIndx) { 188 inpIndx = inpIndx.filter(x => outReady[x]); 189 return inpIndx.length 190 ? { 191 name: `**${inpName}**`, 192 value: `\`\`\`\n${inpIndx.map(x => outReady[x]).join("\n")}\`\`\``, 193 } 194 : ""; 195 } 196 } 197 statsWorker(); 198 199 function beautifier(j) { 200 switch (j) { 201 case 04: 202 return data.firingModes[currStats[j] - 1]; 203 case 09: 204 return data.penetrationLevels[currStats[j] - 1]; 205 case 19: 206 return data.reloadTypes[currStats[j] - 1]; 207 case 08: 208 if (currStats[j] == -1) { 209 return "Infinity"; 210 } else { 211 return parseFloat(currStats[j].toFixed(2)).toString() + " m/s"; 212 } 213 case 03: 214 return parseFloat(currStats[j].toFixed(2)) 215 .toString() 216 .replace(".", " ~ "); 217 default: 218 return parseFloat(currStats[j].toFixed(2)).toString() + addUnit(j); 219 } 220 221 function addUnit(j) { 222 switch (j) { 223 case 7: 224 case 14: 225 case 15: 226 case 23: 227 case 24: 228 case 31: 229 return " ms"; 230 case 25: 231 case 26: 232 case 27: 233 case 28: 234 return " m/s"; 235 case 20: 236 case 21: 237 case 22: 238 return " s"; 239 case 16: 240 return "%"; 241 case 6: 242 return " Rounds"; 243 case 5: 244 return " RPM"; 245 default: 246 return ""; 247 } 248 } 249 } 250 interpretion = currGun.gunname + common.interpretioner(currAttachments); 251 if (currGun.recoil.hr.length > 2) { 252 chart = common.recoilHandler( 253 currGun.recoil.hr, 254 currGun.recoil.vr, 255 currRecoilArr[0], 256 currRecoilArr[1], 257 currRecoilArr[2] 258 ); 259 recoilAvailable = true; 260 } else recoilAvailable = false; 261 262 if (chart == "none") recoilAvailable = false; 263 if (chart == "err") hasError = true; 264 265 const dmg = 266 common.damageHandler( 267 currDRM.damage, 268 currDRM.range, 269 1, 270 100, 271 60000 / currStats[5], 272 currStats[7], 273 currStats[6], 274 currStats[0] 275 ) || "```This should never happen```"; 276 out = [ 277 currGun.description 278 ? { 279 name: "**Description:**", 280 value: `\`\`\`\n${currGun.description}\`\`\``, 281 } 282 : {}, 283 { name: "**Damage Profile:**", value: dmg }, 284 ...out, 285 ]; 286 out = out.filter(x => x.value); 287 return { 288 title: interpretion, 289 color: 5814783, 290 fields: out, 291 footer: { 292 text: "[OUTDATED] All data courtesy of Project Lighthouse 2.0 and CoDM Research Crew", 293 icon_url: 294 "https://media.discordapp.net/attachments/735590814662656102/806960573753327657/cc.png", 295 }, 296 }; 297 }