const dateFormat = require('/usr/local/lib/node_modules/dateformat'); module.exports = { defaultConfig: { enabled: true, debug: true, runs: true, apiKey: '' }, defaultConfigDetails: { debug: { label: 'Print debug messages' }, runs: { label: 'Also log runs' }, apiKey: { label: 'SWDB instance API key', type: 'textarea' } }, pluginName: 'SWDB', pluginDescription: 'Uploads data to SWDB.', target_host: 'localhost', target_port: '80', target_url_run: '/API/v1/log-run', target_url_profile: '/API/v1/log-profile', temp: {}, proxy: null, config: null, /** * Initializes he plugin. * * @param proxy The proxy. * @param Global configurations. */ init(proxy, config) { this.proxy = proxy; this.config = config; proxy.on('apiCommand', (req, resp) => { try { wizardID = ''; command = ''; apiKey = config.Config.Plugins[this.pluginName].apiKey; if (config.Config.Plugins[this.pluginName].enabled) { command = req["command"]; wizardID = req["wizard_id"]; } if (!this.temp[wizardID]) { this.temp[wizardID] = {}; } // USER LOGIN: Upload profile if (command === 'HubUserLogin') { // Check that API key is filled in if (!apiKey) { this.log('error', `Profile upload is enabled, but missing API key. Check ${this.pluginName} settings.`); return; } this.log('info', 'Uploading profile to SWDB...') var request = require('/usr/local/lib/node_modules/request') var querystring = require('/usr/local/lib/node_modules/querystring'); //var http = require('/usr/local/lib/node_modules/http'); var http = require('http'); //var fs = require('/usr/local/lib/node_modules/fs'); var post_data = querystring.stringify({ 'data' : JSON.stringify(resp), 'key' : apiKey }); // An object of options to indicate where to post to var post_options = { host: this.target_host, port: this.target_port, path: this.target_url_profile, method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'Content-Length': Buffer.byteLength(post_data) } }; // Set up the request var resp = "" var post_req = http.request(post_options, function(res) { res.setEncoding('utf8'); res.on('data', function (chunk) { resp = chunk; }); }); // post the data post_req.write(post_data); post_req.end(); } if (command === 'BattleScenarioStart') { //for (var key in req) { // this.log('DEBUG', `IVV SCE START: ${key}: ${req[key]}`); //} if (req["helper_list"] != null || req["mentor_helper_list"] != null || req["npc_friend_helper_list"] != null ){ this.temp[wizardID].helper = 1; } else{ this.temp[wizardID].helper = 0; } this.temp[wizardID].area = req.region_id; this.temp[wizardID].stage = req.stage_no; this.temp[wizardID].difficulty = req.difficulty; } if (command === 'BattleScenarioResult' || command === 'BattleDungeonResult' || command === 'BattleDimensionHoleDungeonResult') { //proxy.log({ type: 'info', source: 'plugin', name: this.pluginName, message: `IVV RUN RESULT: ${resp}` }) for (var key in req) { this.log("info", `IVV REQ: ${key}: ${req[key]}`); } for (var key in resp) { this.log("info", `IVV RES: ${key}: ${resp[key]}`); } this.parse_normal(req, resp); } if (command === 'BattleRiftOfWorldsRaidResult') { this.parse_raid_rift(req, resp); } if (command === 'BattleRiftDungeonResult') { this.parse_elemental_rift(req, resp); } } catch (e) { proxy.log({ type: 'error', source: 'plugin', name: this.pluginName, message: `An unexpected error occured: ${e.message}` }); } }); }, /** * Parses a reward item (no runes!). * * @param crate The crate object. * @return array of {item, unit, pieces, quantity, shapeshifting} */ getItem(crate) { item = 0; unit = 0; pieces = 0; quantity = 0; shapeshifting = 0; if (crate.random_scroll && (crate.random_scroll.item_master_id === 1 || crate.random_scroll.item_master_id === 8 || crate.random_scroll.item_master_id === 2)){ // 1: Unknown scroll // 2: Mystical Scroll // 8: Summoning Stones item = crate.random_scroll.item_master_id; quantity = crate.random_scroll.item_quantity; } if (crate.costume_point) { shapeshifting = crate.costume_point; } if (crate.rune_upgrade_stone) { item = 'Power Stone'; // TODO: Do they exist? quantity = crate.rune_upgrade_stone.item_quantity; } if (crate.unit_info) { unit = crate.unit_info.unit_master_id; } if (crate.material) { item = crate.material.item_master_id; quantity = crate.material.item_quantity; } if (crate.summon_pieces) { pieces = crate.summon_pieces.item_master_id; quantity = crate.summon_pieces.item_quantity; } if (crate.craft_stuff) { item = crate.craft_stuff.item_master_id; quantity = crate.craft_stuff.item_quantity; } drop = {item, unit, pieces, quantity, shapeshifting} return drop; }, /** * TODO! Unaddapted. * Parses a rift reward item (no runes!). * * @param crate The crate object. * @return array of {item, unit, pieces, quantity} */ getItemRift(item, entry) { if (item.type === 8) { const rune = item.info; entry.drop = 'Rune'; entry.grade = `${rune.class}*`; entry.sell_value = rune.sell_value; entry.set = gMapping.rune.sets[rune.set_id]; entry.slot = rune.slot_no; entry.efficiency = gMapping.getRuneEfficiency(rune).current; entry.rarity = gMapping.rune.class[rune.sec_eff.length]; entry.main_stat = gMapping.getRuneEffect(rune.pri_eff); entry.prefix_stat = gMapping.getRuneEffect(rune.prefix_eff); rune.sec_eff.forEach((substat, i) => { entry[`sub${i + 1}`] = gMapping.getRuneEffect(substat); }); } if (item.info.craft_type_id) { enhancement = this.getEnchantVals(item.info.craft_type_id, item.info.craft_type); entry.drop = enhancement.drop; entry.sell_value = item.sell_value; entry.set = enhancement.set; entry.main_stat = enhancement.type; entry.sub1 = enhancement.min; entry.sub2 = enhancement.max; } return entry; }, /** * TODO! Will I need this. * Saves run data to a file in CSV format. * */ saveToFile(entry, filename, headers, proxy) { const csvData = []; const self = this; fs.ensureFile(path.join(config.Config.App.filesPath, filename), err => { if (err) { return; } csv .fromPath(path.join(config.Config.App.filesPath, filename), { ignoreEmpty: true, headers, renameHeaders: true }) .on('data', data => { csvData.push(data); }) .on('end', () => { csvData.push(entry); csv.writeToPath(path.join(config.Config.App.filesPath, filename), csvData, { headers }).on('finish', () => { proxy.log({ type: 'success', source: 'plugin', name: self.pluginName, message: `Saved run data to ${filename}` }); }); }); }); }, /** * Parses a battle data. * Valid for scenario, dungeons and Dimensional Hole. * * @param req The request * @param resp The response. */ parse_normal(req, resp) { const { command } = req; const { wizard_id: wizardID, wizard_name: wizardName } = resp.wizard_info; const run = {}; const run_party = {}; const run_k_party = {}; log = true; if (command === 'BattleDungeonResult') { //for (var key in req) { // this.log("DEBUG", `IVV DUNGEON REQ: ${key}: ${req[key]}`); //} if (req.dungeon_id > 10000){ // Hall of Heroes or unknown log = false; } run.area = req.dungeon_id; run.stage = req.stage_id; run.difficulty = 0 // TODO: Read request run.helper = 0; } if (command === 'BattleScenarioResult') { //for (var key in this.temp[wizardID]) { // this.log("DEBUG", `IVV TEMP: ${key}: ${this.temp[wizardID][key]}`); //} //for (var key in req) { // this.log("DEBUG", `IVV REQ: ${key}: ${req[key]}`); //} run.helper = this.temp[wizardID].helper; run.area = this.temp[wizardID].area; run.stage = this.temp[wizardID].stage; run.difficulty = this.temp[wizardID].difficulty; } if (command === 'BattleDimensionHoleDungeonResult') { //if (gMapping.dungeon[resp.dungeon_id]) { // run.dungeon = `${gMapping.dungeon[resp.dungeon_id]} Level ${resp.difficulty}`; //} //for (var key in req) { // this.log("DEBUG", `IVV DIMENSONALE REQ: ${key}: ${req[key]}`); //} run.area = resp.dungeon_id; run.stage = resp.difficulty; run.difficulty = 0 run.helper = 0; } run.uid = wizardID; run.win = resp.win_lose; // 1/0 2 is lost in scenario run.dtime = dateFormat(new Date(), 'yyyy-mm-dd HH:MM:ss'); const reward = resp.reward ? resp.reward : {}; run.time = req.clear_time ? req.clear_time : 0; run.mana = reward.mana ? reward.mana : 0; run.energy = reward.energy ? reward.energy : 0; run.crystal = reward.crystal ? reward.crystal : 0; // TODO: GET //run.helper = 0; run.rune = {}; run.unit = 0; run.unit_pieces = {}; run.sd = 0; run.item = {}; run.shapeshifting = 0; if (reward.crate) { run.mana = reward.crate.mana ? run.mana + reward.crate.mana : run.mana; run.energy = reward.crate.energy ? run.energy + reward.crate.energy : run.energy; run.crystal = reward.crate.crystal ? run.crystal + reward.crate.crystal : run.crystal; if (reward.crate.rune) { const rune = reward.crate.rune; //for (var key in rune) { // this.proxy.log({ type: 'info', source: 'plugin', name: this.pluginName, message: `IVV RUNE: ${key}: ${rune[key]}` }) //} run.rune.id = rune.rune_id; run.rune.grade = rune.class; run.rune.value = rune.sell_value; run.rune.set = rune.set_id; run.rune.slot = rune.slot_no; run.rune.efficiency = gMapping.getRuneEfficiency(rune).current; run.rune.quality = rune.rank; run.rune.main = rune.pri_eff[0]; run.rune.main_value = rune.pri_eff[1]; if (rune.prefix_eff){ run.rune.innate = rune.prefix_eff[0]; run.rune.innate_value = rune.prefix_eff[1]; } run.rune['substat_1'] = 0; run.rune['substat_1_value'] = 0; run.rune['substat_2'] = 0; run.rune['substat_2_value'] = 0; run.rune['substat_3'] = 0; run.rune['substat_3_value'] = 0; run.rune['substat_4'] = 0; run.rune['substat_4_value'] = 0; rune.sec_eff.forEach((substat, i) => { run.rune[`substat_${i + 1}`] = substat[0]; run.rune[`substat_${i + 1}_value`] = substat[1]; }); } else { for (var key in reward.crate) { this.proxy.log({ type: 'info', source: 'plugin', name: this.pluginName, message: `IVV ITEM: ${key}: ${reward.crate[key]}` }) } drop = this.getItem(reward.crate); if (drop.unit){ run.unit.id = drop.unit; } if (drop.pieces){ run.unit_pieces.id = drop.pieces; run.unit_pieces.quantity = drop.quantity; } if (drop.item){ run.item.id = drop.item; run.item.quantity = drop.quantity; } run.shapeshifting = drop.shapeshifting; } } if (resp.instance_info) { run.sd = resp.instance_info; } if (resp.unit_list && resp.unit_list.length > 0) { resp.unit_list.forEach((unit, i) => { run_party[i] = unit.unit_master_id; run_k_party[i] = unit.unit_id; }); } json_rune = '['; if (run.rune.id != undefined){ json_rune += '{'; json_rune += `"id": "${run.rune.id}", `; json_rune += `"stars": "${run.rune.grade}", `; json_rune += `"type": "${run.rune.set}", `; json_rune += `"slot": "${run.rune.slot}", `; json_rune += `"efficiency": "${run.rune.efficiency}", `; json_rune += `"quality": "${run.rune.quality}", `; // TODO: Get json_rune += `"ancient": 0, `; json_rune += `"value": "${run.rune.value}", `; json_rune += `"main_stat": "${run.rune.main}", `; json_rune += `"main_stat_value": "${run.rune.main_value}", `; json_rune += `"innate_stat": "${run.rune.innate}", `; json_rune += `"innate_stat_value": "${run.rune.innate_value}", `; json_rune += `"substat_1": "${run.rune.substat_1}", `; json_rune += `"substat_1_value": "${run.rune.substat_1_value}", `; json_rune += `"substat_2": "${run.rune.substat_2}", `; json_rune += `"substat_2_value": "${run.rune.substat_2_value}", `; json_rune += `"substat_3": "${run.rune.substat_3}", `; json_rune += `"substat_3_value": "${run.rune.substat_3_value}", `; json_rune += `"substat_4": "${run.rune.substat_4}", `; json_rune += `"substat_4_value": "${run.rune.substat_4_value}"`; json_rune += '}'; } json_rune = json_rune + "]"; json_item = '['; if (run.item.id != undefined){ json_item += '{'; json_item += `"id": "${run.item.id}", `; json_item += `"quantity": "${run.item.quantity}"`; json_item += '}'; } json_item = json_item + "]"; json_unit_pieces = '['; if (run.unit_pieces.length > 0){ json_unit_pieces += '{'; json_unit_pieces += `"id": "${run.unit_pieces.id}", `; json_unit_pieces += `"quantity": "${run.unit_pieces.quantity}"`; json_unit_pieces += '}'; } json_unit_pieces = json_unit_pieces + "]"; json_party = '['; resp.unit_list.forEach((unit, i) => { json_party = json_party + '{"unit_id": ' + run_party[i] + ', "unit_master_id": ' + run_k_party[i] + '},'; }); json_party = json_party.slice(0, -1) + "]"; json = `{`; json += `"uid": "${run.uid}", `; json += `"dtime": "${run.dtime}", `; json += `"area": "${run.area}", `; json += `"stage": "${run.stage}", `; json += `"difficulty": "${run.difficulty}", `; json += `"win": "${run.win}", `; json += `"time": "${run.time}", `; json += `"mana": "${run.mana}", `; json += `"energy": "${run.energy}", `; json += `"crystal": "${run.crystal}", `; json += `"rune": ${json_rune}, `; json += `"sd": ${run.sd}, `; json += `"item": ${json_item}, `; json += `"unit": ${run.unit}, `; json += `"unit_pieces": ${json_unit_pieces}, `; json += `"shapeshifting": ${run.shapeshifting}, `; json += `"party": ${json_party}, `; json += `"helper": "${run.helper}"`; json += `}`; this.log('DEBUG', `json: ${json}`) //const filename = sanitize(`${wizardName}-${wizardID}-runs.csv`); //const filename = sanitize(`IVV-${wizardName}-${wizardID}-runs.csv`); //this.saveToFile(entry, filename, headers, proxy); // Make the request //var inspect = require('/usr/local/lib/node_modules/eyespect').inspector(); var request = require('/usr/local/lib/node_modules/request') var querystring = require('/usr/local/lib/node_modules/querystring'); //var http = require('/usr/local/lib/node_modules/http'); var http = require('http'); //var fs = require('/usr/local/lib/node_modules/fs'); var post_data = querystring.stringify({ 'data' : json, 'key' : apiKey }); // An object of options to indicate where to post to var post_options = { host: this.target_host, port: this.target_port, path: this.target_url_run, method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'Content-Length': Buffer.byteLength(post_data) } }; // Set up the request var resp = "" var post_req = http.request(post_options, function(res) { res.setEncoding('utf8'); res.on('data', function (chunk) { resp = chunk; }); }); // post the data post_req.write(post_data); post_req.end(); }, /** * TODO Unaddapted. * Parses a battle data. * Valid for Rift Raids. * * @param req The request * @param resp The response. */ parse_raid_rift(req, resp) { const { wizard_id: wizardID, wizard_name: wizardName } = resp.wizard_info; let run = {}; if (gMapping.dungeon[req.dungeon_id]) { run.dungeon = `${gMapping.elemental_rift_dungeon[req.dungeon_id]}`; isElemental = true; } //const winLost = resp.win_lose === 1 ? 'Win' : 'Did not kill'; run.dtime = dateFormat(new Date(), 'yyyy-mm-dd HH:MM:ss'); //run.result = winLost; run.win = resp.win_lose; run.rune = {}; run.unit = 0; run.unit_pieces = {}; run.sd = 0; run.item = {}; run.shapeshifting = 0; run.time = req.clear_time ? req.clear_time : 0; const reward = resp.reward ? resp.reward : {}; if (resp.win_lose === 1) { // No crate: Mana of shapeshifting stones if (!reward.crate) { const reward = resp.battle_reward_list.find(value => value.wizard_id === resp.wizard_info.wizard_id).reward_list[0]; if (reward.item_master_id === 6) { run.shapeshifting = reward.item_quantity; } else { run.mana = reward.item_quantity; } } // Rune craft item else if (reward.crate.changestones) { const item = { info: { craft_type: reward.crate.changestones[0].craft_type, craft_type_id: reward.crate.changestones[0].craft_type_id }, sell_value: reward.crate.changestones[0].sell_value }; run.drop= this.getItemRift(item, run); } // Rune else if (reward.crate.rune) { const rune = reward.crate.rune; //for (var key in rune) { // this.proxy.log({ type: 'info', source: 'plugin', name: this.pluginName, message: `IVV RUNE: ${key}: ${rune[key]}` }) //} run.rune.id = rune.rune_id; run.rune.grade = rune.class; run.rune.value = rune.sell_value; run.rune.set = rune.set_id; run.rune.slot = rune.slot_no; run.rune.efficiency = gMapping.getRuneEfficiency(rune).current; run.rune.quality = rune.rank; run.rune.main = rune.pri_eff[0]; run.rune.main_value = rune.pri_eff[1]; if (rune.prefix_eff){ run.rune.innate = rune.prefix_eff[0]; run.rune.innate_value = rune.prefix_eff[1]; } rune.sec_eff.forEach((substat, i) => { run.rune[`substat_${i + 1}`] = substat[0]; run.rune[`substat_${i + 1}_value`] = substat[1]; }); } // Unit (Rainbowmon) else if (reward.crate.unit_info && reward.crate.unit_info.unit_master_id > 0) { run.unit.id = reward.crate.unit_info.unit_master_id; } // Item else if (!run.drop && resp.reward.crate) { //run.drop = this.getItem(reward.resp.reward.crate); if (resp.reward.crate.random_scroll && (resp.reward.crate.random_scroll.item_master_id === 1 || resp.reward.crate.random_scroll.item_master_id === 8 || resp.reward.crate.random_scroll.item_master_id === 2)){ // 1: Unknown scroll // 2: Mystical Scroll // 8: Summoning Stones run.item.id = resp.reward.crate.random_scroll.item_master_id; run.item.quantity = resp.reward.crate.random_scroll.item_quantity; } //if (resp.reward.crate.costume_point) { // shapeshifting = resp.reward.crate.costume_point; //} //if (resp.reward.crate.rune_upgrade_stone) { // item = 'Power Stone'; // TODO: Do they exist? // quantity = resp.reward.crate.rune_upgrade_stone.item_quantity; //} //if (resp.reward.crate.unit_info) { // unit = resp.reward.crate.unit_info.unit_master_id; //} if (resp.reward.crate.material) { item = resp.reward.crate.material.item_master_id; quantity = resp.reward.crate.material.item_quantity; } //if (resp.reward.crate.summon_pieces) { // pieces = resp.reward.crate.summon_pieces.item_master_id; // quantity = resp.reward.crate.summon_pieces.item_quantity; //} if (resp.reward.crate.craft_stuff) { item = resp.reward.crate.craft_stuff.item_master_id; quantity = resp.reward.crate.craft_stuff.item_quantity; } } else { run.drop = 'unknown'; } } if (resp.unit_list && resp.unit_list.length > 0) { resp.unit_list.forEach((unit, i) => { run_party[i] = unit.unit_master_id; run_k_party[i] = unit.unit_id; }); } //const filename = sanitize(`${wizardName}-${wizardID}-raid-runs.csv`); //this.saveToFile(run. filename, headers, proxy); }, /** * TODO Unaddapted. * Parses a battle data. * Valid for Rift Dungeons. * * @param req The request * @param resp The response. */ parse_elemental_rift(req, resp) { const { wizard_id: wizardID, wizard_name: wizardName } = resp.wizard_info; let entry = {}; if (gMapping.dungeon[req.dungeon_id]) { entry.dungeon = `${gMapping.elemental_rift_dungeon[req.dungeon_id]}`; isElemental = true; } const winLost = req.battle_result === 1 ? 'Win' : 'Did not kill'; entry.date = dateFormat(new Date(), 'yyyy-mm-dd HH:MM'); entry.result = winLost; if (resp.item_list && resp.item_list.length > 0) { resp.item_list.forEach((item, i) => { if (item.is_boxing !== 1 || item.id === 2001) { entry[`item${i + 1}`] = `${gMapping.craftMaterial[item.id]} x${item.quantity}`; } else { if (item.id === 2) { entry.drop = 'Mystical Scroll'; } if (item.id === 8) { entry.drop = `Summoning Stones x${item.item_quantity}`; } if (item.info && item.info.unit_master_id > 0) { entry.drop = `${gMapping.getMonsterName(item.info.unit_master_id)} ${item.class}`; } if ((item.info && item.info.craft_type_id) || item.type === 8) { entry = this.getItemRift(item, entry); } } }); } if (resp.unit_list && resp.unit_list.length > 0) { resp.unit_list.forEach((unit, i) => { entry[`team${i + 1}`] = gMapping.getMonsterName(unit.unit_master_id); }); } json_rune = '['; if (run.rune.length() > 0){ json_rune += `"id": "${run.rune.id}", `; json_rune += `"grade": "${run.rune.grade}", `; json_rune += `"set": "${run.rune.set}", `; json_rune += `"slot": "${run.rune.slot}", `; json_rune += `"efficiency": "${run.rune.efficiency}", `; json_rune += `"quality": "${run.rune.quality}", `; json_rune += `"value": "${run.rune.value}", `; json_rune += `"main_stat": "${run.rune.main}", `; json_rune += `"main_stat_value": "${run.rune.main_value}", `; json_rune += `"innate_stat": "${run.rune.innate}", `; json_rune += `"innate_stat_value": "${run.rune.innate_value}", `; json_rune += `"substat_1": "${run.rune.substat_1}", `; json_rune += `"substat_1_value": "${run.rune.substat_1_value}", `; json_rune += `"substat_2": "${run.rune.substat_2}", `; json_rune += `"substat_2_value": "${run.rune.substat_2_value}", `; json_rune += `"substat_3": "${run.rune.substat_3}", `; json_rune += `"substat_4_value": "${run.rune.substat_3_value}", `; json_rune += `"substat_4": "${run.rune.substat_4}", `; json_rune += `"substat_4_value": "${run.rune.substat_4_value}", `; } json_rune = json_party.slice(0, -1) + "]"; json_item = '['; if (run.item.length() > 0){ json_item += `"id": "${run.item.id}", `; json_item += `"quantity": "${run.item.quantity}", `; } json_item = json_party.slice(0, -1) + "]"; json_unit_pieces = '['; if (run.unit_pieces.length() > 0){ json_unit_pieces += `"id": "${run.unit_pieces.id}", `; json_unit_pieces += `"quantity": "${run.unit_pieces.quantity}", `; } json_unit_pieces = json_party.slice(0, -1) + "]"; json_party = '['; resp.unit_list.forEach((unit, i) => { json_party = json_party + '{"unit_id": ' + run_party[i] + ', "unit_master_id": ' + run_k_party[i] + '},'; }); json_party = json_party.slice(0, -1) + "]"; //this.log('DEBUG', `IVV json_party: ${json_party}`) json = `{`; json += `"dtime": "${run.dtime}", `; json += `"area": "${run.dungeon}", `; json += `"stage": "${run.stage}", `; json += `"difficulty": "${run.difficulty}", `; json += `"win": "${run.win}", `; json += `"time": "${run.time}", `; json += `"mana": "${run.mana}", `; json += `"energy": "${run.energy}", `; json += `"crystal": "${run.crystal}", `; json += `"rune": ${json_rune}, `; json += `"sd": ${run.sd}, `; json += `"item": ${json_item}, `; json += `"unit": ${run.unit}, `; json += `"unit_pieces": ${json_unit_pieces}, `; json += `"sapeshifting": ${run.sapeshifting}, `; json += `"party": ${json_party}`; json += `}`; this.log('DEBUG', `json: ${json}`) }, /** * TODO ??? */ getEnchantVals(craftID, craftType) { const map = {}; const typeNumber = Number(craftID.toString().slice(-4, -2)); map.set = gMapping.rune.sets[Number(craftID.toString().slice(0, -4))]; map.grade = gMapping.rune.quality[Number(craftID.toString().slice(-1))]; map.type = gMapping.rune.effectTypes[typeNumber]; if (craftType === 2) { map.min = gMapping.grindstone[typeNumber].range[Number(craftID.toString().slice(-1))].min; map.max = gMapping.grindstone[typeNumber].range[Number(craftID.toString().slice(-1))].max; map.drop = 'Grindstone'; } else { map.min = gMapping.enchanted_gem[typeNumber].range[Number(craftID.toString().slice(-1))].min; map.max = gMapping.enchanted_gem[typeNumber].range[Number(craftID.toString().slice(-1))].max; map.drop = 'Enchanted Gem'; } return map; }, /** * Prints a messageto the SWEX output. * * @param type Log type. Debug type will be printed depending on config. * @param msg The message to log. */ log(type, msg){ //if (type != "debug" || this.config.Config.Plugins[this.pluginName].debug == true){ this.proxy.log({ type: type, source: 'plugin', name: this.pluginName, message: msg }); //} } };