NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name Materia inserter for Ariyala // @version 0.1.5 // @description Provides buttons to automatically insert materia into slots // @author ShadeX91 // @match http://ffxiv.ariyala.com/* // @require https://code.jquery.com/jquery-3.2.1.slim.js // @grant none // ==/UserScript== (function() { 'use strict'; var healers = ["White Mage", "Scholar", "Astrologian"]; var tanks = ["Dark Knight", "Warrior", "Paladin"]; var dpsDex = ["Bard", "Machinist", "Ninja"]; var dpsStr = ["Monk", "Samurai", "Dragoon"]; var dpsInt = ["Black Mage", "Summoner", "Red Mage"]; var prio1 = ["STR", "DHT", "DET", "CRT", "TEN"]; var materiaSelector = $("#materiaWindow .placer:nth-child(2)"); // Materia chances: $("#materiaWindow tr td.right") var prioInput = "<label for='prioInput'>Priorities:</label><input type='text' value='STR, DHT, DET, CRT, SKS, TEN' id='prioInput' style='display:block; margin: 5px auto 15px auto; width: 200px'>"; materiaSelector.append(prioInput); //var debugButton = "<input type='submit' value='Show Debug Info' id='myDebugButton'>"; //materiaSelector.append(debugButton); var testButton = "<input type='submit' value='Fill Materia' id='myTestButton'>"; materiaSelector.append(testButton); //var resetButton = "<input type='submit' value='Reset Materia' id='myResetButton'>"; //materiaSelector.append(resetButton); //document.getElementById("materiaSelect1").selectedIndex=5; //document.getElementById("materiaSelect1").dispatchEvent(new Event("change")); $("#myTestButton").click(function() { $("#materiaTableClearButton").click(); // Use maximum or safe melds var doMaximum = false; // Whether this is a piece of accessory var isAccessory = false; // Total number of available slots var numTotal = 0; // Number of safe materia slots var materiaChances = $("#materiaWindow tr td.right"); var numSafe = 0; // Get number of "safe" materia slots $.each(materiaChances, function(index, value) { if($(value).html() === "100%") numSafe++; }); // If the second select box does not offer Vit, then it is an accessory var vitIndex = getIndexByValue("#materiaSelect2", "VIT:0"); if(vitIndex === -1) { isAccessory = true; } var materiaSelectors = $(".materiaTable select"); $.each(materiaSelectors, function(index, value) { if(! $(value).is(":disabled") ) numTotal++; }); var prios = getPriosFromInput(); // Example values: isAccessory = false, numTotal = 5, numSafe = 2, doMaximum = false var res = calculateMelds(getAttributeOrder(), getAttributesToMax(), prios, numTotal, numSafe, isAccessory, true); // Insert our values into the website for(var i = 0; i < res.length; i++) { $("#materiaSelect"+(i+1)).val(res[i]).change(); } }); // Calculate optimal melds with the given parameters. function calculateMelds(attributes, toMax, priorities, numTotal, numSafe, isAccessory, doMax) { var result = []; var maxVals = toMax; var pIndex = 0; var targetGrade = 5; // TODO: This needs serious cleanup var i=0; while(i < numTotal) { pIndex = 0; targetGrade = 5; if(numSafe - i < 0) { targetGrade = 4; } var attrString = priorities[pIndex]; if(isMainStat(attrString) && isAccessory && i > 0) { while(isMainStat(attrString)) { pIndex++; if(pIndex >= priorities.length) { return result; } attrString = priorities[pIndex]; } } var attrIndex = $.inArray(attrString, attributes); var attrToMax = maxVals[attrIndex]; var matGrade = calculateMateriaGrade(attrString, attrToMax, doMax); if(matGrade >= targetGrade) { matGrade = Math.min(matGrade, targetGrade); result[i] = attrString + ":" + matGrade; maxVals[attrIndex] = attrToMax - getStatsFromMateriaGrade(attrString, matGrade); } else { pIndex++; var found = false; do { attrString = priorities[pIndex]; attrIndex = $.inArray(attrString, attributes); attrToMax = maxVals[attrIndex]; matGrade = calculateMateriaGrade(attrString, attrToMax, doMax); if(matGrade >= targetGrade) { matGrade = Math.min(matGrade, targetGrade); result[i] = attrString + ":" + matGrade; maxVals[attrIndex] = attrToMax - getStatsFromMateriaGrade(attrString, matGrade); found = true; } else if(pIndex+1 < priorities.length) { pIndex++; } else { pIndex = 0; targetGrade--; } } while(targetGrade > 0 && !found); } i++; } return result; } function getPriosFromInput() { var text = $("#prioInput").val().replace(/ /g, ''); var arr = text.split(","); return arr; } function getStatsFromMateriaGrade(attribute, grade) { var values = [2,4,6,9,12,40]; if(isMainStat(attribute)) { values = [1,2,4,7,15,25]; } return values[grade]; } // Calculate which grade materia (0-5) to use depending on the stat we give it function calculateMateriaGrade(attribute, toMax, overfill) { var grade = 0; var values = [2,4,6,9,12,40]; if(isMainStat(attribute)) { values = [1,2,4,7,15,25]; } $.each(values,function(index, value) { if(toMax >= value || (overfill && index==values.length-1 && toMax-value > -15) ) { grade++; } else return false; }); return grade-1; } function isMainStat(attribute) { return $.inArray(attribute, ["STR","DEX","INT","MND","VIT"]) !== -1; } $("#myResetButton").click(function() { $("#materiaTableClearButton").click(); }); $("#myDebugButton").click(function() { var attributes = getAttributesToMax(); // Debug info, current value of attributes and so on. console.log(attributes); console.log(getAttributeOrder()); }); // Not really necessary since we can change selected values via .val(value) function getIndexByValue(selectbox, value) { var count = 0; $(selectbox +" option").each( function(){ if($(this).attr("value") === value) return false; else count++; } ); if(count == $(selectbox +" option").length) return -1; return count; } function getAttributesToMax() { var table = $("#materiaWindow .placer:nth-child(1) tr"); table = table.splice(1,table.length-1); var attributes = []; $(table).each(function(index, value) { var text = $(this).find("td").eq(2).html(); attributes[index] = parseInt(text); }); return attributes; } // Create an array with the order of all attributes for this class function getAttributeOrder() { var playerClass = getClassName(); console.log(playerClass); if($.inArray(playerClass, healers) !== -1) { return ["MND", "DHT", "CRT", "DET", "SPS", "PIE", "VIT"]; } else if($.inArray(playerClass, tanks) !== -1) { return ["STR", "DHT", "CRT", "DET", "SKS", "VIT", "TEN"]; } else if($.inArray(playerClass, dpsStr) !== -1) { return ["STR", "DHT", "CRT", "DET", "SKS", "VIT"]; } else if($.inArray(playerClass, dpsDex) !== -1) { return ["DEX", "DHT", "CRT", "DET", "SKS", "VIT"]; } else if($.inArray(playerClass, dpsInt) !== -1) { return ["INT", "DHT", "CRT", "DET", "SPS", "VIT"]; } else { return []; } } function getClassName() { var playerClass = $("#categoryBoxContentName").html(); return playerClass; } })();